简体   繁体   English

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

[英]Exception handling in fire and forget for C# 5 (in .net 4.5)

Consider the following "fire-and-forget" use case: 考虑以下“即发即弃”用例:

A caller requests some data from my method. 调用者从我的方法请求一些数据。 My method checks the cache to see if the data is already there. 我的方法检查缓存以查看数据是否已存在。 If it's not, it fetches it from the source and caches it. 如果不是,则从源获取并缓存它。 The caller shouldn't need to wait for the caching to occur before getting his results and the method shouldn't prevent the caller from getting a result if the caching happens to fail. 在获得结果之前,调用者不需要等待缓存发生,并且如果缓存失败,该方法不应该阻止调用者获得结果。 What I have today, looks like this: 我今天拥有的,看起来像这样:

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;
}

If CacheFoo throws an Exception it goes unobserved and eventually (in .Net 4.5) it gets swallowed up by the framework. 如果CacheFoo抛出异常,它就会被观察到,最终(在.Net 4.5中)它被框架吞没了。 I'd rather have a last shot at cleaning up the exception myself, but I don't want to block the current thread. 我宁愿自己最后一次清理异常,但我不想阻止当前的线程。 What's the best way to do that? 最好的方法是什么?

Here is what I've tried 这是我尝试过的

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

Is there a better way? 有没有更好的办法? Do I need the "if" statement on IsFaulted or is that redundant because I've already specified "OnlyOnFaulted"? 我是否需要IsFaulted上的“if”语句或者这是多余的,因为我已经指定了“OnlyOnFaulted”?

Any opinions/suggestions would be much appreciated. 任何意见/建议将不胜感激。

Four things: 四件事:

  • No, you don't need the Task.IsFaulted property ; 不,您不需要Task.IsFaulted属性 ; the callback will only fire if it's faulted 只有在出现故障时才会触发回调
  • You don't need to capture cacheTask ; 您不需要捕获cacheTask ; the e in your callback is the same task, so you might as well use that instead. 你的回调中的e是同一个任务,所以你也可以改用它。 (Then the same delegate can be used for all tasks.) (然后相同的代理可以用于所有任务。)
  • If you're always logging in the same way, you may want to write an extension method on task to make it easy to do this 如果您始终以相同的方式登录,则可能需要在任务上编写扩展方法以便于执行此操作
  • As an alternative to adding a handler, you could consider subscribing to TaskScheduler.UnobservedTaskException and performing logging there 作为添加处理程序的替代方法,您可以考虑订阅TaskScheduler.UnobservedTaskException并在那里执行日志记录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM