简体   繁体   English

C#从异步调用中获取结果

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

I have an API that I'm working with and it has limited documentation. 我有一个我正在使用的API,它的文档有限。 I have been told that some of the methods that it executes are called asynchronously. 有人告诉我,它执行的一些方法是异步调用的。

How can I get the result of these asynchronous calls. 如何获得这些异步调用的结果。 Note that I am not doing anything special to call them, the API handles the asynchronous part. 请注意,我没有做任何特殊的事情来调用它们,API处理异步部分。 But I can't seem to get a "reply" back from these calls - I'm assuming that's because they are in another thread. 但我似乎无法从这些调用中得到“回复” - 我假设那是因为他们在另一个线程中。

UPDATE - I've included some of the code below. 更新 - 我已经包含了下面的一些代码。 The API uses an event procedure for the callback but it never seems to fire. 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();
    }

There are several ways that operations can take place asynchronously in .NET. 有几种方法可以在.NET中异步进行操作。 Since you didn't post any specifics, I'll give an overview of the more common patterns: 由于您没有发布任何细节,我将概述更常见的模式:

AsyncWaitHandle AsyncWaitHandle

Often you'll find (especially in the .NET framework classes) pairs of methods named with Begin and End (ie something like BeginReceive and EndReceive ). 通常你会发现(特别是在.NET框架类中)以BeginEnd命名的方法对(即类似BeginReceiveEndReceive )。

Calling the begin function returns an AsyncWaitHandle object, which can be used to synchronize threads like a regular WaitHandle (by calling WaitOne or passing it into the static WaitHandle.WaitAny or WaitHandle.WaitAll functions), then is passed into the corresponding "end" function to obtain the return value of the function (or, if one occurred, throw the exception that was encountered). 调用begin函数会返回一个AsyncWaitHandle对象,该对象可用于同步线程,如常规WaitHandle (通过调用WaitOne或将其传递给静态WaitHandle.WaitAnyWaitHandle.WaitAll函数),然后传递到相应的“end”函数获取函数的返回值(或者,如果发生了一个函数,则抛出遇到的异常)。

If you use the simple .NET facility for calling a method asynchronously (creating a delegate for the function and calling BeginInvoke and EndInvoke ), then this is the approach you'll need to use. 如果您使用简单的.NET工具异步调用方法(为函数创建委托并调用BeginInvokeEndInvoke ),那么这就是您需要使用的方法。 However, most API's that have built-in support for asynchronous operations will handle the actual asynchronous calling part for you, leaving you with properly named BeginXXX and EndXXX functions, rather than forcing you to create a delegate yourself. 但是,大多数具有内置支持异步操作的API将为您处理实际的异步调用部分,让您使用正确命名的BeginXXXEndXXX函数,而不是强迫您自己创建委托。

Sample using the WaitHandle : 使用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);

Often async methods are coupled with events, as shown below. 异步方法通常与事件耦合,如下所示。

Events 活动

Sometimes a method call that completes asynchronously will raise an event upon its completion. 有时,异步完成的方法调用将在完成时引发事件。 This is also sometimes used in combination with the AsyncWaitHandle approach to deliver the notification that the process has completed. 这有时也与AsyncWaitHandle方法结合使用,以提供进程已完成的通知。 For example, the MSMQ libraries have a BeginReceive and EndReceieve function on the queue object, as well as a ReceieveCompleted event. 例如,MSMQ库在队列对象上有一个BeginReceiveEndReceieve函数,以及一个ReceieveCompleted事件。 When the event fires, it indicates that EndReceive can then be called, passing in the AsyncWaitHandle object returned from the call to BeginReceive . 当事件触发,则表明EndReceive然后可以调用,传入AsyncWaitHandle对象从调用返回BeginReceive to get the actual message that was received. 获取收到的实际消息。

Either way, you attach to the event and use it as you would any other event. 无论哪种方式,您都会附加到事件并像使用任何其他事件一样使用它。

Sample using AsyncWaitHandle and events : 使用AsyncWaitHandle和事件的示例

(somewhere in the code) (代码中的某个地方)

object.OperationComplete += object_OperationComplete;

(elsewhere) (别处)

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

These generally work in a variety of ways...you can hold on to the IAsyncResult returned from the Begin operation yourself, but most libraries will pass that IAsyncResult object as a property on their particular EventArgs class. 这些通常以各种方式工作...您可以自己保留从Begin操作返回的IAsyncResult ,但是大多数库将IAsyncResult对象作为其特定EventArgs类的属性传递。

It's also common to find the return value being present as a property on the EventArgs class. 查找返回值作为EventArgs类的属性也很常见。 While using this value is fine, if the Begin operation returned an IAsyncResult , it's always a good idea to call the corresponding End function , even if the data you need is in the EventArgs . 虽然使用这个值很好,但是如果Begin操作返回了IAsyncResult ,那么调用相应的End函数总是一个好主意 ,即使你需要的数据在EventArgs中也是如此。 The End function is usually the way that exceptions are caught, as well. End函数通常也是捕获异常的方式。

Callbacks 回调

A callback (in .NET) is a delegate that is supplied to the asynchronous function. 回调(在.NET中)是提供给异步函数的委托。 Callbacks are used in more than just asynchronous functions, but in this context they're generally a delegate that you supply when calling the function that it will call when it completes. 回调不仅仅用于异步函数,但在这种情况下,它们通常是一个委托,它在调用它完成时将调用的函数时提供。

Callbacks are similar to events (in that they're both delegate-based), though there is more of a one-to-one correlation between the method calls and the callbacks supplied. 回调类似于事件(因为它们都是基于委托的),尽管方法调用和提供的回调之间存在更多的一对一关联。

Example using a callback : 使用回调的示例

object.BeginOperation(args, OperationComplete);

...

void OperationComplete(SomeObject results)
{
    ...
}

Typically you would pass in a reference to a function that the method will "call back" when it is complete. 通常,您将传入对该方法在完成时“回调”的函数的引用。 For a great example of this behaviour, look at the BackgroundWorker and it's RunWorkCompleted event. 有关此行为的一个很好的示例,请查看BackgroundWorker及其RunWorkCompleted事件。 This is set as a property rather than passed in as an argument, but the same idea applies. 这被设置为属性而不是作为参数传递,但同样的想法适用。

If you have some sourcecode, or at least the name of the API you are using, we may be able to be more specific, though. 如果你有一些源代码,或者至少是你正在使用的API的名称,我们可能会更具体。

Here's a basic example of passing in the callback method as an argument: 这是将回调方法作为参数传递的基本示例:

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

There are several idioms for communicating asynchronous results. 有几种用于传递异步结果的习语。 Based on your question, my best guess is that you're dealing with methods that accept delegates they call upon completion ("callbacks"). 基于你的问题,我最好的猜测是你正在处理接受他们在完成时调用的代理的方法(“回调”)。

You have to define a method that matches the delegate type and pass it to the asynchronous method. 您必须定义与委托类型匹配的方法,并将其传递给异步方法。 When it finishes, it invokes your delegate, normally passing the results via one or more of the delegate's parameters. 完成后,它会调用您的委托,通常通过一个或多个委托的参数传递结果。

For example, if you have this asynchronous method: 例如,如果您有此异步方法:

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);

You would call it like this: 你会这样称呼它:

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

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

You get your result from Asynchronous calls by passing a pointer to a callback function. 通过将指针传递给回调函数,可以从异步调用中获得结果。 Please let us know which API you are trying to call, and someone probably will provide you some sample code. 请告诉我们您要调用的API,有人可能会为您提供一些示例代码。

You need to use the BeginInvoke and EndInvoke methods. 您需要使用BeginInvoke和EndInvoke方法。

This article shows how to call a method asynchronously: 本文介绍如何异步调用方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM