在C#中异步使用委托

eto*_*bot 2 c# delegates asynchronous

我有以下代表

delegate void UpdateFileDelegate(long maxFileID);
Run Code Online (Sandbox Code Playgroud)

我是这样从WinForms应用程序调用的

UpdateFileDelegate FD = new UpdateFileDelegate(ClassInstance.UpdateFile);
FD.BeginInvoke(longIDNumber,null,null);
Run Code Online (Sandbox Code Playgroud)

它以异步方式运行,但我遇到的问题是如何判断Method何时完成执行,以便让最终用户知道?

更新:感谢以下建议,以下代码可以解决问题.此文章也有助于我了解我的代码实际上在做什么.

delegate void UpdateFileDelegate(long maxFileID);
UpdateFileDelegate FB = new UpdateFileDelegate(ClassInstance.UpdateFile);
AsyncCallback callback = new AsyncCallback(this.CallBackMethod);
IAsyncResult result = FB.BeginInvoke(longIDNumber);

private void CallBackMethod(IAsyncResult result)
    {
     AsyncResult delegateResult = (AsyncResult)result;

     UpdateFileDelegate fd = (UpdateFileDelegate)delegateResult.AsyncDelegate;
     fd.EndInvoke(result);
     MessageBox.Show("All Done!");
    }
Run Code Online (Sandbox Code Playgroud)

Dav*_*eer 7

请参阅异步调用同步方法

BeginInvoke会返回一个IAsyncResult,这使得许多不同的方式来了解,当它完成,如用它的AsyncWaitHandle.WaitOne()方法.这取决于你在此期间做了什么.

或者您可以将回调方法的委托传递给BeginInvoke.这可以说是最强大的策略,但有时候是矫枉过正.


Han*_*ant 7

在返回的IAsyncResult引用上调用EndInvoke非常重要.这是查明委托目标是否完成执行而没有任何异常的唯一方法.如果不这样做,这样的异常将落入bit-bucket,你的程序将无法正常执行.您可以在调用BeginInvoke()的同一线程上调用EndInvoke,也可以在回调中执行.在同一个线程上调用它很少有用,你几乎总是会失去异步执行的好处.一些示例代码演示了这两个并强调了异常处理:

using System;
using System.Runtime.Remoting.Messaging;

class Program {
  static void Main(string[] args) {
    new Program().Run();
    Console.ReadLine();
  }
  void Run() {
    Action example = new Action(threaded);
    IAsyncResult ia = example.BeginInvoke(new AsyncCallback(completed), null);
    // Option #1:
    /*
    ia.AsyncWaitHandle.WaitOne();
    try {
      example.EndInvoke(ia);
    }
    catch (ApplicationException ex) {
      Console.WriteLine(ex.Message);
    }
    */
  }

  void threaded() {
    throw new ApplicationException("Kaboom");
  }

  void completed(IAsyncResult ar) {
    // Option #2:
    Action example = (ar as AsyncResult).AsyncDelegate as Action;
    try {
      example.EndInvoke(ar);
    }
    catch (ApplicationException ex) {
      Console.WriteLine(ex.Message);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您不希望代码抛出异常,则不应在完成回调中使用try块.这可确保您的程序在终止时终止.