如何处理Task.Runexception
我从Task.Run中捕获exception时遇到了问题。我更改了代码并解决了问题。 我愿意弄清楚在这两种方式下处理Task.Run中的exception有什么区别:
在Outside函数中我无法捕获exception但在Inside中我可以捕获它。
void Outside() { try { Task.Run(() => { int z = 0; int x = 1 / z; }); } catch (Exception exception) { MessageBox.Show("Outside : " + exception.Message); } } void Inside() { Task.Run(() => { try { int z = 0; int x = 1 / z; } catch (Exception exception) { MessageBox.Show("Inside : "+exception.Message); } }); }
运行任务时,如果某些内容等待任务的结果或任务完成,则会保留并重新抛出它抛出的任何exception。
Task.Run()
返回一个可用于执行此操作的Task
对象,因此:
var task = Task.Run(...) try { task.Wait(); // Rethrows any exception(s). ...
对于较新版本的C#,您可以使用await
而不是任务.Wait():
try { await Task.Run(...); ...
这更整洁。
为了完整起见,这是一个可编译的控制台应用程序,演示了使用await
:
using System; using System.Threading; using System.Threading.Tasks; namespace ConsoleApp1 { class Program { static void Main() { test().Wait(); } static async Task test() { try { await Task.Run(() => throwsExceptionAfterOneSecond()); } catch (Exception e) { Console.WriteLine(e.Message); } } static void throwsExceptionAfterOneSecond() { Thread.Sleep(1000); // Sleep is for illustration only. throw new InvalidOperationException("Ooops"); } } }
使用Task.Wait的想法会做到这一点,但会导致调用线程(如代码所示)等待并因此阻塞,直到任务完成,这有效地使代码同步而不是异步。
而是使用Task.ContinueWith选项来实现结果:
Task.Run(() => { //do some work }).ContinueWith((t) => { if (t.IsFaulted) throw t.Exception; if (t.IsCompleted) //optionally do some work); });
如果任务需要在UI线程上继续,请将TaskScheduler.FromCurrentSynchronizationContext()选项作为参数继续使用,如下所示:
).ContinueWith((t) => { if (t.IsFaulted) throw t.Exception; if (t.IsCompleted) //optionally do some work); }, TaskScheduler.FromCurrentSynchronizationContext());
此代码将简单地从任务级别重新抛出聚合exception。 当然,您也可以在此处介绍其他forms的exception处理。
在您的外部代码中,您只检查启动任务是否不会抛出exception而不是任务的正文本身。 它以异步方式运行,然后启动它的代码。
您可以使用:
void Outside() { try { Task.Run(() => { int z = 0; int x = 1 / z; }).GetAwaiter().GetResult(); } catch (Exception exception) { MessageBox.Show("Outside : " + exception.Message); } }
使用.GetAwaiter().GetResult()
等待任务结束并按原样传递抛出的exception,并且不将它们包装在AggregateException
。
对我来说,我希望我的Task.Run在出错后继续运行,让UI处理错误,因为它有时间。
我的(奇怪的?)解决方案是运行Form.Timer。 我的Task.Run有它的队列(对于长时间运行的非UI东西),我的Form.Timer有它的队列(用于UI的东西)。
由于此方法已经适用于我,因此添加error handling是微不足道的:如果task.Run收到错误,它会将错误信息添加到Form.Timer队列,该队列显示错误对话框。
您可以等待,然后exception冒泡到当前的同步上下文(请参阅Matthew Watson的回答)。 或者,正如Menno Jongerius所提到的,您可以使用ContinueWith
来使代码保持异步。 请注意,只有在使用OnlyOnFaulted
continuation选项引发exception时才能这样做:
上述就是C#学习教程:如何处理Task.Runexception分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
Task.Run(()=> { //.... some work.... }) // We could wait now, so we any exceptions are thrown, but that // would make the code synchronous. Instead, we continue only if // the task fails. .ContinueWith(t => { // This is always true since we ContinueWith OnlyOnFaulted, // But we add the condition anyway so resharper doesn't bark. if (t.Exception != null) throw t.Exception; }, default , TaskContinuationOptions.OnlyOnFaulted , TaskScheduler.FromCurrentSynchronizationContext());
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/987180.html