请考虑以下使用CancellationTokenSource的基本任务库功能的代码.它启动一个线程,它填充一个字典的价格,并从sql Server数据库读取数据.线程在大约10分钟后结束,每2个小时再次启动,首先调用Cancel,以防线程仍在运行.
private CancellationTokenSource mTokenSource = new CancellationTokenSource(); internal Prices(Dictionary<string,Dealer> dealers) { mDealers = dealers; mTask = Task.Factory.StartNew (() => ReadPrices(mTokenSource.Token),mTokenSource.Token); } internal void Cancel() { mTokenSource.Cancel(); } private void ReadPrices(CancellationToken ct) { using (sqlConnection connection = new sqlConnection(ConfigurationManager.AppSettings["DB"])) { connection.open(); var dealerIds = from dealer in mDealers.Values where dealer.Id != null select dealer.Id; foreach (var dealerId in dealerIds) { if (!ct.IsCancellationRequested) { FillPrices(connection); } else break; } } }
在某些时候,应用程序在事件日志中遇到以下异常.
Application: Engine.exe Framework Version: v4.0.30319 Description: The
process was terminated due to an unhandled exception. Exception Info:
System.AggregateException Stack: at
System.Threading.Tasks.TaskExceptionHolder.Finalize()
解决方法
任务喜欢听的.这听起来好像不快乐.尽管如此,您可以获得“最后的机会”:
TaskScheduler.UnobservedTaskException += (sender,args) => { foreach (var ex in args.Exception.InnerExceptions) { Log(ex); } args.Setobserved(); };
请注意,这不是解决方案 – 它的目的是让您看到任务正在爆炸以及出现什么错误. Setobserved()将阻止它杀死您的应用程序.但这里的解决方案是理想的:
>不要让你的任务抛出,
>或者确保你在那里检查任务的状态
您的取消检测可能不太满意. IIRC的首选方法是:
foreach(...) { if(ct.IsCancellationRequested) { // any cleanup etc ct.ThrowIfCancellationRequested(); } ... }
或者更简单,如果不需要清理,只需:
foreach(...) { ct.ThrowIfCancellationRequested(); ... }
原文地址:https://www.jb51.cc/csharp/96600.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。