在火灾中处理异常并忘记C#5(在.net 4.5中)

amodi 发布于 2019-03-09 asynchronous 最后更新 2019-03-09 14:33 4 浏览

考虑下面的“即丢即用”用例: 调用者从我的方法中请求一些数据。我的方法检查缓存以查看数据是否已经存在。如果不是,它从源中提取并缓存它。调用者在得到他的结果之前不需要等待缓存发生,并且如果缓存发生故障,该方法不应该阻止调用者获得结果。我今天看到的是这样的:

public Foo GetFoo(string fooKey)
{
    // look for Foo with fooKey in cache
    // if Foo is not found, get Foo with fooKey from source
    // and assign it to local variable myFoo
    Task cacheTask 
           = Task.Run
                (
                    () => CacheFoo(myFoo)// fire-and-forget the caching of myFoo
                ); 
    return myFoo;
}
如果CacheFoo抛出一个异常,它就会被忽略,最终(在.Net 4.5中)它会被框架吞噬掉。我宁愿自己清理异常,但我不想阻止当前线程。什么是最好的方式来做到这一点? 这是我试过的
try
{
    ...
   cacheTask.ContinueWith
            (
                (e) => { 
                         if (cacheTask.IsFaulted) 
                            { 
                             /* log cacheTask.Exception */; 
                             } 
                        }
                , TaskContinuationOptions.OnlyOnFaulted
            ); 
}
有没有更好的办法?我是否需要IsFaulted上的“if”声明或者是否已经指定了“OnlyOnFaulted”? 任何意见/建议将不胜感激。
已邀请:

vanimi

赞同来自:

四件事:

  • 不,你不需要Task.IsFaulted property;只有在出现故障时才会触发回调
  • 您无需捕获cacheTask;你的回调中的e是同一个任务,所以你不妨使用它。 (然后同一个代表可以用于所有任务。)
  • 如果您总是以相同的方式登录,您可能希望在任务上编写扩展方法以便于执行此操作
  • 作为添加处理程序的替代方法,您可以考虑订阅TaskScheduler.UnobservedTaskException并执行日志记录