2010-04-13 64 views
2

我有一個我正在使用的API,它的文檔有限。我被告知它執行的一些方法是異步調用的。C#從異步調用中獲取結果

如何獲得這些異步調用的結果。請注意,我沒有做任何特殊的調用,API處理異步部分。但我似乎無法從這些調用中得到「回覆」 - 我假設這是因爲它們在另一個線程中。

更新 - 我已經包含了下面的一些代碼。 API使用事件過程來進行回調,但它似乎從未觸發過。

public partial class Window1 : Window 
{ 
    ClientAppServer newServer= new ClientAppServer(); 

    public Window1() 
    { 
     InitializeComponent(); 
     newServer.ReceiveRequest += ReadServerReply; 
    } 


    private void ReadServerReply(RemoteRequest rr) 
    { 

     MessageBox.Show("reading server reply"); 
     if ((rr.TransferObject) is Gateways) 
     { 
      MessageBox.Show("you have gateways!"); 
     } 
    } 


    private void login() 
    { 
      newServer.RetrieveCollection(typeof(Gateways), true); 

    } 


    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     this.login(); 
    } 
+0

有.NET中不同的模式做異步調用。你能提供一些示例代碼嗎? – 2010-04-13 15:27:38

+1

發表一些代碼。通常,異步API調用將委託作爲參數 - 只要您調用的任何對象完成,就會調用該委託。委託方法是您的程序中您可以獲得「回覆」的地方。 – MusiGenesis 2010-04-13 15:29:04

+0

如果API提供了異步方法,那麼它必須提供方法/事件來獲取這些異步方法的結果,或者自己封裝這些方法。 – Bobby 2010-04-13 15:29:24

回答

6

有一些操作可以在.NET中發生異步的幾種方法。既然你沒有張貼任何細節,我給比較常見的模式概述:

AsyncWaitHandle

通常你會發現(特別是在.NET框架類)的方法對命名與BeginEnd(即類似BeginReceiveEndReceive)。

調用開始函數返回一個AsyncWaitHandle對象,它可用於像同步線程常規WaitHandle(通過調用WaitOne或者將它傳遞到靜態WaitHandle.WaitAnyWaitHandle.WaitAll函數),然後被傳遞到相應的「結束」功能獲取函數的返回值(或者,如果發生了,則拋出遇到的異常)。

如果您使用簡單的.NET工具異步調用方法(爲函數創建委託並調用BeginInvokeEndInvoke),那麼這是您需要使用的方法。但是,大多數內置支持異步操作的API將爲您處理實際的異步調用部分,而使用正確命名的BeginXXXEndXXX函數,而不是強制自己創建委託。使用

樣品的WaitHandle

IAsyncResult result = object.BeginOperation(args); 

result.AsyncWaitHandle.WaitOne(); 
// that will cause the current thread to block until 
// the operation completes. Obviously this isn't 
// exactly how you'd ordinarily use an async method 
// (since you're essentially forcing it to be 
// synchronous this way) 

returnValue = object.EndOperation(result); 

通常異步方法加上事件,如下圖所示。

活動

有時,完成它的異步完成後,將引發事件的方法調用。這有時也會與AsyncWaitHandle方法結合使用,以傳遞過程已完成的通知。例如,MSMQ庫在隊列對象上具有BeginReceiveEndReceieve函數,以及ReceieveCompleted事件。當事件觸發時,表示可以調用EndReceive,將從呼叫返回的AsyncWaitHandle對象傳遞給BeginReceive。獲取收到的實際消息。

無論採用哪種方式,您都會附加到該事件並像其他任何事件一樣使用它。

樣品使用AsyncWaitHandle和事件

(代碼中的某處)

object.OperationComplete += object_OperationComplete; 

(其他地方)

IAsyncResult result = object.BeginOperation(args); 

// at this point, you can either wait for the event 
// to fire, or use the WaitHandle approach as shown 
// in the previous example 

... 

void objectOperationComplete(object sender, AsyncOperationEventArgs e) 
{ 
    returnValue = object.EndOperation(e.AsyncResult); 
} 

這些一般工作在各種不同的方式...您可以保留自己從Begin操作返回的IAsyncResult,但大多數庫會通過臨時t IAsyncResult對象作爲其特定EventArgs類中的屬性。

找到作爲EventArgs類的屬性的返回值也很常見。如果Begin操作返回IAsyncResult,則使用該值時正確無誤,,即使您需要的數據位於EventArgs中,調用相應的End函數總是一個好主意。 End函數通常也是捕獲異常的方式。

回調

的回調(在.NET)是被提供給異步函數的委託。回調函數不僅用於異步函數,在這種情況下,它們通常是您在調用完成時調用的函數時提供的委託。

回調與事件類似(因爲它們都是基於委託的),儘管方法調用和提供的回調之間存在更多的一對一關聯。

實施例使用回調

object.BeginOperation(args, OperationComplete); 

... 

void OperationComplete(SomeObject results) 
{ 
    ... 
} 
0

通過將指針傳遞給回調函數,可以從異步調用中獲得結果。請讓我們知道您嘗試撥打哪個API,並且有人可能會爲您提供一些示例代碼。

2

通常情況下,您會傳入一個函數的引用,該方法在完成時將「回調」。有關此行爲的一個很好的示例,請查看BackgroundWorker及其RunWorkCompleted事件。這被設置爲一個屬性而不是作爲參數傳入,但同樣的想法適用。

但是,如果您有一些源代碼,或者至少是您使用的API的名稱,我們可能會更具體。

這裏的回調方法作爲參數傳遞的一個基本的例子:

public SearchForm : Form 
{ 
    public void StartSearch(string searchtext) 
    { 
     searcher.SearchAsync(searchtext, SearchCompleted); 
    } 

    public void SearchCompleted(IList<SearchResult> results) 
    { 
     // Called by the async searcher component, possibly on another thread 

     // Consider marshalling to the UI thread here if you plan to update the UI like this: 
     if (InvokeRequired) 
     { 
      Invoke(new Action<IList<SearchResult>>(SearchCompleted), results); 
      return; 
     } 

     foreach (var result in Results) 
     { 
      AddToList(result); 
     } 
    } 
} 
+0

我認爲這個答案是正確的。我認爲關鍵在於評論代碼。我將如何能夠將它編組爲與UI – 2010-04-13 16:37:00

+0

相同的線程,我修改了示例以假定它在Form上工作,因此調用了Form.InvokeRequired和Form.Invoke。 – 2010-04-13 22:42:10

1

有幾種成語用於傳送異步結果。基於你的問題,我最好的猜測是你正在處理接受委託他們完成調用的方法(「回調」)。

您必須定義匹配委託類型並將其傳遞給異步方法的方法。完成後,它會調用委託,通常通過一個或多個委託參數傳遞結果。

舉例來說,如果你有這樣的異步方法:

public class Foo { 
    public static void DoSomethingAsynchronous(SimpleCallback simpleCallback) { 

     // First this method does something asynchronous 

     // Then it calls the provided delegate, passing the operation's results 
     simpleCallback(true); 
    } 
} 

// The result parameter can be much richer - it's your primary mechanism for 
// passing results back to the caller. 
public delegate SimpleCallback(bool result); 

你會這樣稱呼它:

public static void Main(string[] args) { 
    Foo.DoSomethingAsynchronous(WriteResultToConsole); 
} 

// Here's your SimpleCallback 
public static WriteResultToConsole(bool result) { 
    Console.WriteLine(result? "Success!" : "Failed!"); 
} 
+0

有趣。如果沒有回調並使用事件過程呢? – 2010-04-13 16:35:53