开始结束异步方法调用
本文关键字:调用 异步方法 结束 开始 | 更新日期: 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。