簡體   English   中英

C#從異步調用中獲取結果

[英]C# getting the results from an asynchronous call

我有一個我正在使用的API,它的文檔有限。 有人告訴我,它執行的一些方法是異步調用的。

如何獲得這些異步調用的結果。 請注意,我沒有做任何特殊的事情來調用它們,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();
    }

有幾種方法可以在.NET中異步進行操作。 由於您沒有發布任何細節,我將概述更常見的模式:

AsyncWaitHandle

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

調用begin函數會返回一個AsyncWaitHandle對象,該對象可用於同步線程,如常規WaitHandle (通過調用WaitOne或將其傳遞給靜態WaitHandle.WaitAnyWaitHandle.WaitAll函數),然后傳遞到相應的“end”函數獲取函數的返回值(或者,如果發生了一個函數,則拋出遇到的異常)。

如果您使用簡單的.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 ,但是大多數庫將IAsyncResult對象作為其特定EventArgs類的屬性傳遞。

查找返回值作為EventArgs類的屬性也很常見。 雖然使用這個值很好,但是如果Begin操作返回了IAsyncResult ,那么調用相應的End函數總是一個好主意 ,即使你需要的數據在EventArgs中也是如此。 End函數通常也是捕獲異常的方式。

回調

回調(在.NET中)是提供給異步函數的委托。 回調不僅僅用於異步函數,但在這種情況下,它們通常是一個委托,它在調用它完成時將調用的函數時提供。

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

使用回調的示例

object.BeginOperation(args, OperationComplete);

...

void OperationComplete(SomeObject results)
{
    ...
}

通常,您將傳入對該方法在完成時“回調”的函數的引用。 有關此行為的一個很好的示例,請查看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);
        }
    }
}

有幾種用於傳遞異步結果的習語。 基於你的問題,我最好的猜測是你正在處理接受他們在完成時調用的代理的方法(“回調”)。

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

例如,如果您有此異步方法:

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!");
}

通過將指針傳遞給回調函數,可以從異步調用中獲得結果。 請告訴我們您要調用的API,有人可能會為您提供一些示例代碼。

您需要使用BeginInvoke和EndInvoke方法。

本文介紹如何異步調用方法:

http://support.microsoft.com/kb/315582

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM