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

Bil*_*our 8 c# error-handling asynchronous task-parallel-library .net-4.5

考虑以下"即发即弃"用例:

调用者从我的方法请求一些数据.我的方法检查缓存以查看数据是否已存在.如果不是,则从源获取并缓存它.在获得结果之前,调用者不需要等待缓存发生,并且如果缓存失败,该方法不应该阻止调用者获得结果.我今天拥有的,看起来像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)

如果CacheFoo抛出异常,它就会被观察到,最终(在.Net 4.5中)它被框架吞没了.我宁愿自己最后一次清理异常,但我不想阻止当前的线程.最好的方法是什么?

这是我尝试过的

try
{
    ...
   cacheTask.ContinueWith
            (
                (e) => { 
                         if (cacheTask.IsFaulted) 
                            { 
                             /* log cacheTask.Exception */; 
                             } 
                        }
                , TaskContinuationOptions.OnlyOnFaulted
            ); 
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?我是否需要IsFaulted上的"if"语句或者这是多余的,因为我已经指定了"OnlyOnFaulted"?

任何意见/建议将不胜感激.

Jon*_*eet 10

四件事:

  • 不,您不需要Task.IsFaulted属性 ; 只有在出现故障时才会触发回调
  • 你不需要捕捉cacheTask; 在e你的回调是相同的任务,所以你还不如用这来代替.(然后相同的代理可以用于所有任务.)
  • 如果您始终以相同的方式登录,则可能需要在任务上编写扩展方法以便于执行此操作
  • 作为添加处理程序的替代方法,您可以考虑订阅TaskScheduler.UnobservedTaskException并在那里执行日志记录

  • @ГеннадийВанинНовосибирск:是的,有区别,虽然我不确定它在这里是否相关.如果任务以未观察到的方式出现故障,.NET 4.0将终止整个过程..NET 4.5没有. (3认同)