开始结束异步方法调用

Fat*_*ror 1 c# multithreading asynchronous begininvoke .net-3.5

这是Microsoft的代码片段.我对异步方法调用有疑问.

因为我们正在调用end.Invoke在Begin-invoke之后看起来我们正在进行同步调用.因为我们正在等待异步调用的返回值.

如果异步方法在调用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() ) );
}
Run Code Online (Sandbox Code Playgroud)

Ned*_*nov 5

如果异步方法在调用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() ) );
}
Run Code Online (Sandbox Code Playgroud)

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

如果你正在尝试做的是运行在后台线程长时间运行的方法,你可以简单地使用Task.Run在.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() ) );
}
Run Code Online (Sandbox Code Playgroud)