关于:AsyncContextThread
https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext
https://github.com/StephenCleary/AsyncEx/blob/master/src/Nito.AsyncEx.Context/AsyncContextThread.cs
没有真正介绍如何处理线程启动时发生的捕获异常。
public partial class MyService : ServiceBase
{
private readonly AsyncContextThread _thread = new AsyncContextThread();
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
public MyService()
{
InitializeComponent();
}
public void Start()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
try
{
_thread.Factory.Run(StartAsync);
}
catch (Exception ex)
{
// Exception?
}
}
private async Task StartAsync()
{
throw new Exception("things went wrong");
}
protected override void OnStop()
{
if (!_cts.IsCancellationRequested)
_cts.Cancel();
_thread.JoinAsync().GetAwaiter().GetResult();
}
}
我似乎没有抓住catch{}
块中的任何内容,此外我尝试将这些添加到我的Program.cs(主入口点)。
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
但是,上述代码中都没有触发任何事件处理程序方法。
问)在这种情况下如何正确处理异常?
作为旁注,我很确定先前使用AsyncContext
并在Visual Studio中调试确实捕获了异常,因此我不确定是否存在某些同步。在尝试为异常添加处理程序时,我缺少上下文。
修改
我知道我可以在try/catch
方法中StartAsync
,但我得到的一点是能够捕获任何未处理的异常,并确保我可以记录它们。
答案 0 :(得分:3)
您可以使用Continuation来处理例外情况。
protected override void OnStart(string[] args)
{
_thread.Factory.Run(StartAsync).ContinueWith(t =>
{
var aggregate = t.Exception.Flatten();
foreach(var exception in aggregate.InnerExceptions)
{
// Handle exception
}
}, TaskContinuationOptions.OnlyOnFaulted);
}
答案 1 :(得分:2)
我一直想写一篇关于异步Win32服务的博客文章......几年了......:)
没有真正介绍如何处理线程启动时发生的捕获异常。
AsyncContextThread
实际上是在创建后立即启动的。您在OnStart
上正在做的是将工作排到其上下文中。
从Task
返回的Run
上观察到该工作的例外情况,观察它的适当方法是使用await
:
protected override async void OnStart(string[] args)
{
try
{
await _thread.Factory.Run(StartAsync);
}
catch (Exception ex)
{
// Exception!
}
}
一些注意事项:
通常情况下,您应该avoid async void
。该规则的例外是事件处理程序或类似事件的方法(例如OnStart
)。当您 使用async void
时,您应该考虑在整个try
方法主体(我们这样做)周围catch
/ async void
。< / p>
await
is superior to ContinueWith
。在这种特殊情况下,ContinueWith
可以正常工作,但在一般情况下,这是不可取的:它不理解async
个委托,它不使用适当的默认TaskScheduler
,它确实不使用适当的默认延续标志。这些都是await
为您处理的所有事情。