在什么情况下会使用
public async Task AsyncMethod(int num)
而不是
public async void AsyncMethod(int num)
我能想到的唯一场景是,如果您需要任务能够跟踪其进度。
另外,在下面的方法中,async和await关键字是不必要的吗?
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
1)通常情况下,您希望返回
2)
static async void f()
{
await h();
}
static async Task g()
{
await h();
}
static async Task h()
{
throw new NotImplementedException();
}
private void button1_Click(object sender, EventArgs e)
{
f();
}
private void button2_Click(object sender, EventArgs e)
{
g();
}
private void button3_Click(object sender, EventArgs e)
{
GC.Collect();
}
public static async void AsyncMethod2(int num)
{
await Task.Factory.StartNew(() => Thread.Sleep(num));
}
是的,在这里使用
有关详细信息,请参阅:http://msdn.microsoft.com/en-us/magazine/jj991977.aspx
我看到了这篇由JRME Laban编写的关于
底线是
这背后的原因是AsyncVoidMethodBuilder使用的同步上下文,在本例中为none。当没有环境同步上下文时,异步void方法主体未处理的任何异常都将在线程池上重新抛出。虽然似乎没有其他合乎逻辑的地方可以抛出这种未经处理的异常,但不幸的结果是进程被终止,因为线程池上未经处理的异常自。NET2.0以来有效地终止了进程。您可以使用AppDomain.UnhandleDexception事件截获所有未处理的异常,但无法从此事件恢复进程。
在编写UI事件处理程序时,异步void方法在某种程度上并不痛苦,因为异常的处理方式与非异步方法相同;它们被扔到调度员身上。有可能从这些例外中恢复过来,在大多数情况下是完全正确的。但是,在UI事件处理程序之外,使用异步void方法是危险的,而且可能不太容易找到。
我从这些陈述中清楚地知道了。
不能用Catch捕获来自异步Void方法的异常
private async void ThrowExceptionAsync()
{
throw new InvalidOperationException();
}
public void AsyncVoidExceptions_CannotBeCaughtByCatch()
{
try
{
ThrowExceptionAsync();
}
catch (Exception)
{
// The exception is never caught here!
throw;
}
}
这些异常可以使用AppDomain.UnhandleDexception或类似的GUI/ASP.NET应用程序的catch-all事件来观察,但是使用这些事件进行常规异常处理会导致不可维护(它会使应用程序崩溃)。
异步void方法具有不同的组合语义。返回Task或Task的异步方法可以使用await,Task.WhenAny,Task.WhenAll等轻松组合。返回void的异步方法并不提供一种简单的方法来通知调用代码它们已经完成。启动几个异步void方法很容易,但确定它们何时完成并不容易。异步void方法将在它们开始和完成时通知它们的SynchronizationContext,但是自定义SynchronizationContext对于常规应用程序代码来说是一个复杂的解决方案。
异步Void方法在使用同步事件处理程序时非常有用,因为它们直接在SynchronizationContext上引发异常,这与同步事件处理程序的行为方式类似
有关详细信息,请查看此链接https://msdn.microsoft.com/en-us/magazine/jj991977.aspx