【发布时间】:2017-04-21 02:55:24
【问题描述】:
我对这个 async/await 概念非常陌生,所以对于提出任何显而易见的问题,我深表歉意。
我需要发送电子邮件,而新的 API 要求我使用 async 并等待。问题是我的很多方法都需要同步调用这个“发送电子邮件”。
所以,我创建了一个同步包装方法:
private Task SendEmailAsync(string email, string content)
{
...
...
...
}
private void SendEmail(string email, string content)
{
Task tsk = Task.Factory.StartNew(async () => await SendEmailAsync(email, content));
try { tsk.Wait(); }
catch (AggregateException aex)
{
throw aex.Flatten();
}
}
但由于某种原因,tsk.Wait() 不会等待 await SendEmailAsync(...) 完成。所以,我需要添加ManualResetEvent。像这样的
private void SendEmail(string email, string content)
{
ManualResetEvent mre = new ManualResetEvent(false);
Task tsk = Task.Factory.StartNew(async () =>
{
mre.Reset();
try { await SendEmailAsync(email, content); }
finally { mre.Set(); }
});
mre.WaitOne();
try { tsk.Wait(); }
catch (AggregateException aex)
{
throw aex.Flatten();
}
}
但是 SendEmailAsync(...) 抛出的任何异常都不会被 tsk.Wait() 捕获。我的问题是:
- 为什么 tsk.Wait() 不等待 await SendEmailAsync(...)
- 如何捕获 await SendEmailAsync(...) 引发的异常
谢谢!
【问题讨论】:
-
拨打
SendEmailAsync(email, content).GetAwaiter().GetResult(); -
要以同步方式运行异步代码,请参见此处stackoverflow.com/a/5097066/5062791
-
你不应该做“同步异步”,因为它往往会导致死锁! Stephen Cleary 很快就会在这里指出这一点;-),但如果你真的需要,我可以推荐 Stephen Toub (blogs.msdn.microsoft.com/pfxteam/2012/01/20/…) 的 AsyncPump。但这不应该在你的库“内部”使用。
-
请参考 Stephen Cleary 的博客,blog.stephencleary.com/2012/07/dont-block-on-async-code.html
-
StartNew is Dangerous: "...由于 StartNew 不理解异步委托,因此该任务实际上代表的只是该委托的开始..."
标签: c# .net async-await uwp task