AsyncContext - > AsyncContextThread处理异常
关于:AsyncContextThread
AsyncContext - > 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;
但是在上面的代码中没有触发事件处理程序方法。
Q)在这种情况下你如何正确处理异常?
作为一个方面说明,我相当确定以前使用AsyncContext
并在Visual Studio中进行调试确实发现了异常,所以我不确定是否有某种同步。上下文我很想念,当试图添加异常处理程序。
编辑
我知道我可以在StartAsync
方法中try/catch
,但我在获得关键是能够捕捉任何未处理的异常,并确保我可以登录他们。
我一直做异步的Win32服务......现在几年一篇博客文章... :)
它真不是盖的如何处理捕获例外线程启动时发生。
AsyncContextThread
实际上在创建后立即启动。你在做什么OnStart
是排队工作的上下文。
对这项工作的例外是在从Run
返回Task
观察,并观察它适当的方法是使用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
方法体(我们这样做)。
await
is superior to ContinueWith
。在这种特殊情况下,ContinueWith
可以正常工作,但在一般情况下,这是不可取的:它不理解async
代表,它不使用适当的默认TaskScheduler
,它不使用适当的默认延续标志。这些都是await
只是为你处理。
感谢Stephen的回复,只是跟进,我有'public void Start()'方法在Visual Studio中调试时运行,我应该试着获取awaiter和它的结果,或者只是把它作为service.Start();? – peteski
我想你必须使用'Start()'。由于它不返回任务,因此无法阻止它。 –
您可以使用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);
}
我明白什么你在说,我认为我希望得到Stephen关于这个问题的意见的原因是他的书“C#Cookbook中的并发”(第35/36页)讨论了在异步void类型方法中处理异常。给出的代码示例并没有使用延续,而是使用了代码示例中的try/catch,因此这看起来不正确。 – peteski
我拼命希望斯蒂芬Cleary回答这个问题:) – peteski
我认为你需要'等待''try'中的方法来捕获异常。目前异步方法将立即返回给调用者,抛出的错误将丢失。 – Equalsk
@Equalsk你不能在Windows服务的OnStart方法中“等待”任何东西,因为它是一个覆盖,并且必须匹配预期的签名。 AsyncContext/AsyncContextThread的整个想法(据我所知)是允许你从不允许的地方启动异步方法(即控制台应用程序或Windows服务)。 – peteski