在任务c#中不等待地重新触发异常
我有一个GUI应用程序,我想在其中运行任务中的某些内容,因此它不会保存UI。我希望将任务中未处理的异常传播到应用程序级异常处理程序。 然而:在任务c#中不等待地重新触发异常,c#,exception,task,C#,Exception,Task,我有一个GUI应用程序,我想在其中运行任务中的某些内容,因此它不会保存UI。我希望将任务中未处理的异常传播到应用程序级异常处理程序。 然而: 如果我只是在任务中抛出一个异常,它将不会达到应用程序级别 除非我使用wait/await,否则会出现异常 Async/Await—我从UI构造函数调用该方法,因此不能在那里使用Async/Await,因为我需要继续构造。我只想执行任务,然后忘记 我在考虑使用dispatcher.invoke,你觉得怎么样 public MainWindow() {
public MainWindow()
{
InitializeComponent();
MyMethodAsync();
InitializeA();
IntiializeB();
}
private void MyMethodAsync()
{
Task t = Task.Run(() =>
{
//Do some stuff
throw new Exception("Throwing some unexpected exception");
}).ContinueWith(MyContinueWith);
}
private void MyContinueWith(Task task)
{
if (task.IsFaulted && task.Exception != null)
{
dispatcher.BeginInvoke(new Action(() =>
{
throw task.Exception;
}), null);
}
}
我可以想到两种方法。首先,是注册事件并记录您需要的内容:
private void MyMethodAsync()
{
// Note you should probably register only once, so this may not fit here.
TaskScheduler.UnobservedTaskException += (s, e) => GlobalLogger.Log(e);
Task t = Task.Run(() =>
{
// Do some staff
}).ContinueWith(MyContinueWith);
}
出于某些原因,您不想使用的更好的选择是实际等待操作并将其包装在一个try catch
:
private async Task MyMethodAsync()
{
try
{
await Task.Run(() =>
{
// Do some staff
});
InvokeContinuation();
}
catch (Exception e)
{
// Log.
}
}
请务必意识到,通过调用Task.Run,您通常会生成一个新线程,而这在大多数情况下不太可能是您想要的。在一些正在进行CPU绑定工作的实例中创建新线程是有意义的,在这些情况下,您将考虑考虑利用其他来获得最大化。相反,如果您的工作受I/O限制,您应该能够一直使用异步调用
为了等待异步方法调用的结果或异常冒泡到调用点,您可以始终附加一个调用,以继续执行异步方法返回的任务。如果您同时处理结果和任何可能的异常,那么异步/等待语义工作得很好。但是请注意,默认情况下,在这些延续中执行的代码可能不会在与原始线程相同的线程中执行。按照惯例,后缀为“Async”的方法通常是返回已启动任务的方法。使用async/await关键字,调用方会自动处理这一问题,其实实现并不重要。@skippy:
await
不会阻塞您的UI。听起来wait
正是您想要的行为。为什么要使用任务。是否继续使用?确实不推荐使用,您应该使用C#5wait
。单是调试的潜力就使得使用任务变得疯狂。继续使用。感谢您的快速回答。我不想使用wait的原因是我想在UI线程上运行的构造函数中使用MyMethodAsync。因此,我不想等待和举行我的窗口建设。(我无法将构造函数设置为异步)我已使用此commentHi Yuval编辑了该问题,正如我之前评论的那样,我与-await的问题是,我希望在UI构造函数中使用MyMethodAsync,而我不希望使用await保留构造函数操作,我只想跑然后忘记。@skippy然后选择第一个选项。我已经选中了第一个选项,但它似乎没有帮助。只有当任务由GC收集时,它才会转到事件(我不知道它何时发生,除非调用GC.Collect,否则它不会到达我的示例中的处理程序)。我现在注意到,当它是GC时,异常将被抛出,并到达我的应用程序级异常处理程序,这很好,但我仍然希望在异常发生时到达那里,而不是依赖于某个时间GC@skippy然后您需要同步或异步等待。同步-我不能,因为它将保存我的UI,异步地。。。?我如何做到这一点(不回到同样的问题上)