當前位置:首頁 » 廢水回用 » 用委託實現回調

用委託實現回調

發布時間: 2020-12-15 04:58:07

⑴ andle::Invoke」類型的已垃圾回收委託進行了回調

手頭有個C++的DLL,是公司的一個遠程通話功能組件。長久以來,這個DLL對外只有三個操作介面。而從合理的角度來說,這個DLL本應再提供一些回調介面或事件之類的東西,用於在通話狀態被動改變時通知外層應用程序。不過銀行里的規矩多多,不能用ActiveX;而使用回調,卻又似不那麼的穩定,尤其在與C#交互時。所以才一直就這么用著。

直到最近,外層應用程序的開發人員提意見抱怨這個DLL。於是,一狠心,決定向這個DLL添加回調的支持。雖然不能確定之前使用回調不穩定的問題在哪,但現有資料和之前自己單獨寫的測試卻都表明C#向C++傳遞的回調是可以正常工作的。因此,必定是這個DLL的什麼地方存在錯誤才會不穩定,大不了搭上一個周末的時間,總應該能解決吧。

一般來說,實現回調的要點就兩點:

1. 回調應加上WINAPI或CALL關鍵字,以聲明其調用方式;

2. 注意參數類型尤其是長度,在C++和C#中的聲明要一致;避免使用指針和引用類型。

由於之前已經單獨測試過,所以就差在DLL中實戰演練了。花了一天時間,根據他們的要求改好了程序。為了避免遇到傳說中的住在迷宮里的那個會吃迷路的人的魔鬼。其間還打了幾針預防針,先在定義回調時先排除了任何字元參數,只用整數;然後去掉了之前的那個中間DLL。原來的核心DLL是MFC擴展動態鏈接庫,不能直接用在C#中,所以又在外邊套了個正規DLL。雖然間接調用DLL很正常,但讓結構更簡單,總沒有壞處。

一切妥當,開始調試,改掉幾個小問題後,發現程序竟然正常的跑起來了,回調的輸出歡快的顯示到屏幕上了。又各式各樣的環境各測了幾遍,依然OK,看來這次運氣不差,哈。接下來打包,寫介面和回調說明文檔,畫狀態圖。

在發出去前,想起來又改了改一些調試和日誌信息,然後又神經質的測試了一把。事後證明,這是一個讓人後悔也慶幸的動作。因為,這次遇到Demo的老兄Demon了,哎,怎一個慘字了得.....

幸虧本命年的我早有時刻面對打擊的覺悟,早前沒有得意忘形,要不這下心情落差大去了。額,不過,來就來吧,有周末兩天做後盾,不信搞不定你。

看看Demon老兄說了些啥:SYSTEM.WINDOWS.FORMS.NI.DLL 0xC0000005 access violation。

完全摸不著頭腦,只能慢慢來了。

先檢查了一遍DLL程序,應該沒有問題,所有的回調也都是在主線程上觸發的,應該跟線程也沒有關系。

再來確定到底是C++ DLL的還是C# EXE的問題,把DLL和EXE在DEBUG和Release下各編譯了一份,然後組合運行了一下,發現當且僅當使用EXE的Release版程序時,會出現該異常。那麼,就應該是C#程序的問題了。

這只是一個非常簡單的示例,實在想不明白代碼可能會有什麼問題。而且還是Debug正常,Release異常。先改改編譯選項試試,把Optimze Code關了試試,問題照舊;再把Define Debug constant開了,這就跟Debug版本的編譯選項完全一樣了,還是不行。看來此路不通了。

看看Google同學有沒有遇到過這樣的問題,把Demon老兄說的搜了一下,結果沒有相關資料…看來這下有得頭疼了。

忽然想起似乎剛才DLL和EXE組合測試的時刻似乎出過一個挺不尋常的提示。再去找找看,發現Debug版的DLL和Release版的EXE一起運行會有這樣的提示:

File: i386\chkesp.c
Line: 42

The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

再搜索一下,這次倒有不少同樣不幸的人,不過正如那句話「不幸的人各有各的不幸」,他們的原因似乎跟我的情況扯不上啥關系。

這下沒招了,再求助Bai一下,看看大家用C++回調C#代碼都遇到些啥情況。結果試了好幾個關鍵字,都一無所獲,正當我感覺鴨梨很大的時候,突然間,用關鍵字「C++ C# 回調 委託」搜到了一個有點意思的帖子 C#處理C++庫回調報錯_非託管代碼傳遞委託被垃圾回收,雖然這位老兄什麼都沒說明,不過貼上來的異常內容很特別:

檢測到 CallbackOnCollectedDelegate
Message: 對「HBVideoParser!Videocomm.Video.HB.HBSDK+SrcDataParseCBHandler::Invoke」類型的已垃圾回收委託進行了回調。這可能會導致應用程序崩潰、損壞和數據丟失。向非託管代碼傳遞委託時,託管應用程序必須讓這些委託保持活動狀態,直到確信不會再次調用它們。

向C++傳遞的委託對象回垃圾回收了,導致回調時異常?感覺有點怪怪,不過死馬當活馬醫吧,改Demo,傳了一個全局委託對象給DLL,再測試~哈,回調輸出又歡快滴出來了~

看來果真如此了,確認一下,改回原來的傳遞臨時對象的方式,在Demo的Main函數里加個異常捕獲,發現確實異常會傳遞到此處,內容則是「Object reference not set to an instance of an object」。雖然與上述的不一致,不過應該就是一回事啦。

現在想想,這也不難理解。C#中通過引用計數來判斷對象是否可被回收,在Demo中,創建的臨時委託對象只是被臨時使用了一下,沒有任何引用,雖然在C++ DLL中保存了,但儼然那已經不屬於Demo的范圍了。因此被垃圾回收很正常。

再想到之前自己單獨寫的測試似乎並沒有發現這樣的問題,那又是為什麼呢?難道因為程序佔用內在太少還沒來得及進行垃圾回收操作?再去翻出來,點住調用按鈕不放,果然,在輸出三四十條信息之後程序異常了。

⑵ c# 委託實現非同步回調是怎麼一回事

義一個委託,該委託於你需要非同步執行的方法的簽名一定要一樣,
另外回 在定義委託時,還可以答加上兩個可選的參數
意思就是說
你的方法簽名 public string TestMethod(int i)
你的委託這樣 public delegate string AsyncMethod(int i);
在程序裡面,你可以這樣用
實例化你的委託:
// ad.TestMethod 假設TestMethod方法包含在一個ad的對象中
AsyncMethod caller = new AsyncMethod(ad.TestMethod);
IAsyncResult Result = caller.BeginInvoke(1,null/*回調*/,new StateObject() /*StateObject是你的對象*/);

這個你調用會返回IAsyncResult 對象 在上面 就是Result
你可以這樣獲得你的對象
Result.AsyncState 但是必須強制轉換。

你可以在MSDN中看一下

⑶ 委託為什麼叫回調

回調(callback)函數是Windows編程的一個重要部分。如果您具備C或C++編程背景,應該就曾在許多Windows API中使用版過回調。Visual Basic添加權了AddressOf關鍵字後,開發人員就可以利用以前一度受到限制的API了。回調函數實際上是方法調用的指針,也稱為函數指針,是一個非常強大的編程特性。.NET以委託的形式實現了函數指針的概念。它們的特殊之處是,與C函數指針不同,.NET委託是類型安全的。這說明,C中的函數指針只不過是一個指向存儲單元的指針,我們無法說出這個指針實際指向什麼,像參數和返回類型等就更無從知曉了。如本章所述,.NET把委託作為一種類型安全的操作。本章後面將學習.NET如何將委託用作實現事件的方式。

詳情咨詢
http://book.csdn.net/bookfiles/829/

⑷ 聲明一個委託public delegate void atcallfack( int x);則用該委託產生的回調方法的原型應該是__

public void MethodName(int temp)
{

}

⑸ 請問委託非同步回調函數是否可以獲得執行後的內容(跨項目)

static void process_Callback(IAsyncResult result)
{
int value = Convert.ToInt32(ar.AsyncState);
AsyncResult aResult = (AsyncResult)ar;
putNewWeibo temp = (putNewWeibo)aResult.AsyncDelegate;
int result = temp.EndInvoke(ar);
}

⑹ 委託,事件和回調函數這3者之間到底是什麼關

這是因為你的回調委託作用域問題。在回調時,委託已經被回收了 所謂成員變數: class test{ public delegate a; public void foo(){ private delegate b; } } 像這種情況,b委託的作用域只在foo()函數裡面,如果你讓b被非託管代碼回調,當foo執行完後,非託管代碼回調時很可能b已被回收了。所以出現這個錯。 a委託是test類的成員變數,它是可以一直保持的,除非你對test進行了析構。 也可以使用static的變數。 也就是說,盡量擴大你的委託的作用域,保證在回調是它不會被自動回收就行了。

⑺ C# 中 委託 和C++中 回調的區別是什麼

C#中。委託可以實現回調。。線程安全的一種實現方式。C#中,事件也是委託。C++不太明了。CLI我都跳過了的。。

⑻ C#事件與委託,事件與回調的用法區別

事件包括:事件發送者、事件接收者和事件處理程序。
關於事件,我們首要知道的是事件的發送者必須知道發送什麼類型的事件,以及相關
的事件參數。而事件的接收者必須了解其事件的處理方法必須使用的返回類型和參數

事件的發送者和事件的接收者都只關注事件而不是對方,這樣對象就只需考慮自己,而不用
考慮其他對象。

例如:足球運動員踢球射門時,產生一個擊球事件,但他並不用關心守門員是誰,他
只要關心自己踢球的角度、力度等事件參數,而守門員也一樣,他只需關注如何接球即可。

足球運動員踢出球,產生一個擊球事件,但是訂閱該事件的可能並不只守門員,其他球員包括己
方和對方球員,甚至包括觀眾和裁判,他們都應該訂閱該事件,因為球接下來會怎麼樣是未
知的,他們都應該做出相應的事件處理方法。

總之,一個事件總是由一個對象產生,但是一個事件可以由多個對象響應。

當多個對象訂閱同一個事件時,IDE(Integrated Development Environment)就會把它們的事
件處理程序一個接一個地串起來關聯到這個事件,並按照訂閱順序,先後執行。可以用+=增加事
件處理函數。

在上面中,我們一直講事件觸發時會調用對應的事件處理方法。但是,問題是他怎麼知道調用
誰的事件處理方法。任何一個對象只要訂閱了事件,他的是事件處理程序就會得到調用。然而
,事件對此該如何管理呢?

這就需要一個新的類型,叫做委託。
通過委託可以創建一個引用變數,但是並不是指向類的實例,而是指向一個類中的某個方法。

設計.NET事件的5步驟:
1):定義參數類型:從類型EventArgs派生出滿足要求的事件參數類
2):定義事件處理者委託:與第一步相關該步一般被泛型委託取代了
3):定義事件成員:在自定義類中,由事件處理者委託定義一個或多個事件成員
4):觸發事件:自定義類的引發事件方法中,通知所有事件訂閱者
5):訂閱事件:注冊事件處理程序
參數object sender 是產生這個事件對象的一個引用,例如處理一個按鈕的單擊事件,sender就
表示別單擊的這個按鈕。
如果沒有事件數據,則傳遞 Empty,而不要傳遞 null。

可能你會執著於這樣的一個問題:既然有了委託,那麼事件干什麼用的呢?
顯然,委託可以干很多事情,但是他不知道什麼時候干,這時候就需要事件來驅動。

或許你還會糾結於這樣的一個問題:那為什麼不直接讓事件自己直接去做呢?
這就得回歸到面向對象的思想上面了,面向對象講究專注,就是一個對象最好只專注
自己的本職工作就可以,其他的事情就由其他相關的對象自己完成。

你想想,如果你是個老闆,你可以觸發一個事件(相當於你有某件事情),但如果處理這個事件
還要讓你自己去做,你會覺得很麻煩,於是你就可以讓你的職員(委託)去執行這些事件處理程序,
你只要在辦公室里等待回復就可以了,這樣是不是輕鬆了許多!

可能你沒有當老闆的命,無法體會,但換個例子,假如你想要買一張火車票,在沒有委託之前,
毫無疑問,你得自己前晚火車站買票,但有了委託後,你就輕鬆了,你只要上網點擊訂票發布
一個事件,你的委託就會直接幫你買票,而你就不用大老遠的自己跑去買票了。

生活中的例子其實很多,我們的父母其實一直充當著委託這個角色,在這里,感激他們一下:你
們辛苦了。

之前,我們說足球運動員踢球時會產生一個擊球事件,並把這個擊球事件與守門員直接聯系
起來,這其實是不準確的,但我只是為了說明事件的作用而已。

准確的說,擊球事件應該是足球運動員和球的,而球和守門員之間的事件應該是球飛出的事件。
現在我們要討論的是這個擊球事件:

既然如此,
那麼假設,球場還有別的球,你可能無意中 幫這些球也訂購了由運動員引發的擊球事件,這樣
子會造成一個後果,足球運動員一踢球這些所有的球都飛出去了。
後果嚴重把!

下面是關於回調的一些定義:(Callback Method)

回調:一個對象將一個方法的引用(方法的引用用委託保存)傳入另一個對象,使得只有他能返
回信息,這就是一個回調。

回調方法是一種在操作或活動完成時由委託自動調用的方法。

回調不同於事件,回調不能發布,不是類型,是一種設計模式,回調在兩個類之間建立一種關系,
其中一個對象會自動對另一個對象做出反應,回調一般是私有的,保存回調的類對於誰能訪問這個
回調有所控制,回調通常在對象的構造函數中設置。

本人粗略定義:簡單的說就是將委託作為參數傳遞給某個特定對象。

這樣,有了回調我們就可以避免上面非賽場上的球也飛出去的問題了。

⑼ c#委託的回調 怎麼個調

最典型的應用,就是在非同步調用時進行回調,看看MSDN上的例子吧。 using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; // State object for reading client data asynchronously public class StateObject { // Client socket. public Socket workSocket = null; // Size of receive buffer. public const int BufferSize = 1024; // Receive buffer. public byte[] buffer = new byte[BufferSize]; // Received data string. public StringBuilder sb = new StringBuilder(); } public class AsynchronousSocketListener { // Thread signal. public static ManualResetEvent allDone = new ManualResetEvent(false); public AsynchronousSocketListener() { } public static void StartListening() { // Data buffer for incoming data. byte[] bytes = new Byte[1024]; // Establish the local endpoint for the socket. // The DNS name of the computer // running the listener is "host.contoso.com". IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); // Create a TCP/IP socket. Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); // Bind the socket to the local endpoint and listen for incoming connections. try { listener.Bind(localEndPoint); listener.Listen(100); while (true) { // Set the event to nonsignaled state. allDone.Reset(); // Start an asynchronous socket to listen for connections. Console.WriteLine("Waiting for a connection..."); listener.BeginAccept( new AsyncCallback(AcceptCallback), listener ); // Wait until a connection is made before continuing. allDone.WaitOne(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } public static void AcceptCallback(IAsyncResult ar) { // Signal the main thread to continue. allDone.Set(); // Get the socket that handles the client request. Socket listener = (Socket) ar.AsyncState; Socket handler = listener.EndAccept(ar); // Create the state object. StateObject state = new StateObject(); state.workSocket = handler; handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } public static void ReadCallback(IAsyncResult ar) { String content = String.Empty; // Retrieve the state object and the handler socket // from the asynchronous state object. StateObject state = (StateObject) ar.AsyncState; Socket handler = state.workSocket; // Read data from the client socket. int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { // There might be more data, so store the data received so far. state.sb.Append(Encoding.ASCII.GetString( state.buffer,0,bytesRead)); // Check for end-of-file tag. If it is not there, read // more data. content = state.sb.ToString(); if (content.IndexOf("<EOF>") > -1) { // All the data has been read from the // client. Display it on the console. Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content ); // Echo the data back to the client. Send(handler, content); } else { // Not all data received. Get more. handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } } } private static void Send(Socket handler, String data) { // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(data); // Begin sending the data to the remote device. handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } private static void SendCallback(IAsyncResult ar) { try { // Retrieve the socket from the state object. Socket handler = (Socket) ar.AsyncState; // Complete sending the data to the remote device. int bytesSent = handler.EndSend(ar); Console.WriteLine("Sent {0} bytes to client.", bytesSent); handler.Shutdown(SocketShutdown.Both); handler.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { StartListening(); return 0; } }

求採納

⑽ 委託就是回調么非同步跟回調又有什麼區別 如果不是 他們我該怎麼去區別和理解或者他們三個有什麼關聯

你是新手吧,委託就是你委託證券公司為你進行股票買賣,回調是指股價上升一段行情後又下跌一小段行情,非同步這詞在股票里邊好像沒有吧

熱點內容
丁度巴拉斯情人電影推薦 發布:2024-08-19 09:13:07 瀏覽:886
類似深水的露點電影 發布:2024-08-19 09:10:12 瀏覽:80
《消失的眼角膜》2電影 發布:2024-08-19 08:34:43 瀏覽:878
私人影院什麼電影好看 發布:2024-08-19 08:33:32 瀏覽:593
干 B 發布:2024-08-19 08:30:21 瀏覽:910
夜晚看片網站 發布:2024-08-19 08:20:59 瀏覽:440
台灣男同電影《越界》 發布:2024-08-19 08:04:35 瀏覽:290
看電影選座位追女孩 發布:2024-08-19 07:54:42 瀏覽:975
日本a級愛情 發布:2024-08-19 07:30:38 瀏覽:832
生活中的瑪麗類似電影 發布:2024-08-19 07:26:46 瀏覽:239