我正在运行静态main()并执行app.Run()来启动WPF窗口。基本上,它首先是带有大量用户控件的viewmodel。用户从那里单击连接按钮,该按钮将在另一个静态类中启动Task.Run()。
当我的任务遇到异常时,它们会冒泡回到app.Run()而不是连接按钮。我猜他们正在向调用线程报告而不是从任务开始的位置。我可以在任务级别处理一些错误,但其他错误则需要用户看到。
所以我的问题是,如何将这些错误发送到UI?
我当前的异步....
private static async void MainMountLoopAsync()
{
try
{
if (_ctsMount == null) _ctsMount = new CancellationTokenSource();
var ct = _ctsMount.Token;
var task = Task.Run(() =>
{
while (!ct.IsCancellationRequested)
{
MoveAxes();
}
}, ct);
await task;
task.Wait(ct);
AbortSlew();
MainLoopRunning = false;
SkySystem.ConnectSerial = false;
IsSkyConnected = SkySystem.ConnectSerial;
}
catch (OperationCanceledException)
{
MainLoopRunning = false;
MonitorLog.LogToMonitor(MonitorDevice.Telescope, MonitorCategory.Server, MonitorType.Information,
$"{MethodBase.GetCurrentMethod().Name}, {Thread.CurrentThread.ManagedThreadId}, Cancel Main Loop Task Requested");
}
catch (Exception ex)
{
MainLoopRunning = false;
MonitorLog.LogToMonitor(MonitorDevice.Telescope, MonitorCategory.Server, MonitorType.Error,
$"{MethodBase.GetCurrentMethod().Name}, {Thread.CurrentThread.ManagedThreadId}, Message:{ex.Message} Stack:{ex.StackTrace}");
AlertState = true;
throw;
}
}
答案 0 :(得分:1)
简而言之,您的 Exception 是未被观察到的(也就是说,您正在起火而忘记了任务)。
一些注意事项:
如果您使用的是Task.Run()
,然后使用Task.ContinueWith,则有许多示例。但是,解雇任务的好处(宽松使用的术语)是,您可以检查调用方法是否抛出异常并进行相应处理。
更进一步,请使用async
和await
。它负责连续性和错误处理,释放了UI,几乎在各个方面都更加整洁。
示例
public void ContinueWithOperation()
{
Task<string> t = Task.Run(() => LongRunningOperation("Continuewith", 500));
t.ContinueWith((t1) =>
{
// check t1 for errors here
Console.WriteLine(t1.Result);
});
}
//Fake async! very smelly
public async Task AsyncOperation()
{
try
{
string t = await Task.Run(() => LongRunningOperation("AsyncOperation", 1000));
Console.WriteLine(t);
}
catch (Exception e)
{
// check for errors here
}
}
// Ideally
public async Task OperationAsync()
{
try
{
string t = await LongRunningOperationAsync("AsyncOperation", 1000);
Console.WriteLine(t);
}
catch (Exception e)
{
// check for errors here
}
}