2009-12-09 102 views
2

我有以下的委托在C#中使用委托异步

delegate void UpdateFileDelegate(long maxFileID); 

,我从WinForms应用程序调用,像这样

UpdateFileDelegate FD = new UpdateFileDelegate(ClassInstance.UpdateFile); 
FD.BeginInvoke(longIDNumber,null,null); 

它异步运行,但我的问题是我怎么能告诉当方法完成后,我可以让最终用户知道吗?

更新: 由于下面的建议,下面的代码会诀窍。 此外,这article有助于让我了解我的代码实际上在做什么。

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

回答

7

Calling Synchronous Methods Asynchronously

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

或者您可以将回调方法的代理传递给BeginInvoke。这可以说是最强大的战略,但有时却是过度杀伤力。

7

在返回的IAsyncResult引用上调用EndInvoke非常重要。只有这样,才能确定代理目标是否完成执行而无任何例外。如果你不这样做,那么这样的例外就会陷入一点点的困境,你的程序将无法正常执行。您可以在调用BeginInvoke()的同一线程上调用EndInvoke,也可以在回调中调用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); 
    } 
    } 
} 

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

+0

如果代码决定不关心异步任务会发生什么(例如,因为用户点击了“取消”),但“取消”请求没有立即响应,那么正确的模式是什么?只需简单地安排其回调调用'EndInvoke'并死掉,然后放弃它(确定回调将保持活动状态,直到任务完成或处理取消请求,然后回调将执行并清理“IAsyncResult”? – supercat 2012-03-19 20:04:13