加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 运行System.Threading.Tasks.Task时异常

发布时间:2020-12-15 17:41:31 所属栏目:百科 来源:网络整理
导读:请考虑以下使用CancellationTokenSource的基本任务库功能的代码.它启动一个线程,它填充一个字典的价格,并从SQL Server数据库读取数据.线程在大约10分钟后结束,每2个小时再次启动,首先调用Cancel,以防线程仍在运行. private CancellationTokenSource mTokenSo
请考虑以下使用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();
    ...
}

同样地,它可能只是一个数据访问异常.在与数据库通信时可能会发生任何数量的异常.超时,死锁,无法连接等

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读