开始结束异步方法调用

本文关键字:调用 异步方法 结束 开始 | 更新日期: 2023-09-27 18:03:41

下面是来自Microsoft的代码片段。我对异步方法调用有疑问。

,因为我们正在调用end。在开始调用之后调用,看起来我们正在进行同步调用。因为我们正在等待异步调用的返回值。

如果异步方法在调用end.invoke时没有完成会发生什么。

我们可以继续下一条语句吗?

如果这发生在多线程环境中,他们如何处理回调信号来纠正线程。

public void DemoEndInvoke()
{
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;
    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);  
    // Do some useful work here. This would be work you want to have
    // run at the same time as the asynchronous call.
    // Retrieve the results of the asynchronous call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;  
    MessageBox.Show (string.Format ("The delegate call returned the string:   '"{0}'", 
                               and the number {1}", s, iExecThread.ToString() ) );
}

开始结束异步方法调用

如果异步方法在执行时没有完成会发生什么调用end.invoke。我们能继续下一个陈述吗等。

是,EndInvoke为阻塞呼叫。如果你使用TaskFactory,你可以让整个事情变得更容易使用。FromAsync方法。这将转换你的API返回一个任务,你可以await

你的代码应该看起来像这样(我还没有编译它):

public async void DemoEndInvoke()
{
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;
    await Task.Factory.FromAsync(MethodDelegate.BeginInvoke, MethodDelegate.EndInvoke, iExecThread);
    MessageBox.Show (string.Format ("The delegate call returned the string:   '"{0}'", and the number {1}", s, iExecThread.ToString() ) );
}

使用await,编译器将生成一个状态机,它保存当前的SynchronizationContext,然后在任务完成后恢复它,并在相同的SynchronizationContext上执行方法的其余部分。如果在UI线程上执行await,则在await之后的代码也将在UI线程上执行。但对于主机应用和单元测试,情况并非如此。

如果你想做的是在后台线程上运行一个长时间运行的方法,你可以简单地使用Task。在。net 4.5或TaskFactory中运行。StartNew在。net 4.0。要了解两者的区别,请参阅本文。

public async void DemoEndInvoke()
{
    await Task.Run(() => this.LongRunningMethod());
    MessageBox.Show (string.Format ("The delegate call returned the string:   '"{0}'", and the number {1}", s, iExecThread.ToString() ) );
}

你必须等待;从异步调用同步方法:

EndInvoke可能会阻塞调用线程,因为它在异步调用完成之前不会返回

用于执行阻塞的机制可能类似于以下内容:

IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);
// wait for async invocation to complete
ar.AsyncWaitHandle.WaitOne()

但是必须调用EndInvoke(参见此问题以获得更多讨论)。

如果不想等待,则需要使用异步回调来执行EndInvoke:

dlgt.BeginInvoke(3000, out iExecThread, ar => dlgt.EndInvoke(out iExecThread, ar), null);

当你这样做的时候,你将不知道你的异步调用的结果;您无法获得返回值,并且您将不知道对任何out参数进行了什么更改(与直觉相反,BeginInvoke根本没有更改任何out参数)。


话虽如此,.NET从。net 4开始获得了优秀的异步编程api;新的模式结构更好,功能更强大,更容易使用(特别是在4.5中)。如果你有选择的话,你应该看看。net 4的TPL和。net 4.5的TAP。