C# 5 中的异常处理和遗忘(在 .net 4.5 中) [英] Exception handling in fire and forget for C# 5 (in .net 4.5)

查看:35
本文介绍了C# 5 中的异常处理和遗忘(在 .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;
}

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

If CacheFoo throws an Exception it goes unobserved and eventually (in .Net 4.5) it gets swallowed up by the framework. 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?

这是我尝试过的

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

有没有更好的办法?我需要关于 IsFaulted 的if"语句还是因为我已经指定了OnlyOnFaulted"而多余?

Is there a better way? Do I need the "if" statement on IsFaulted or is that redundant because I've already specified "OnlyOnFaulted"?

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

Any opinions/suggestions would be much appreciated.

推荐答案

四件事:

  • 不,您不需要 Task.IsFaulted 属性;回调只会在出现故障时触发
  • 您不需要捕获cacheTask;您的回调中的 e 是相同的任务,因此您不妨改用它.(然后同一个委托可以用于所有任务.)
  • 如果您总是以相同的方式登录,您可能需要在任务上编写一个扩展方法,以便轻松完成此操作
  • 作为添加处理程序的替代方法,您可以考虑订阅TaskScheduler.UnobservedTaskException 并在那里执行日志记录
  • No, you don't need the Task.IsFaulted property; the callback will only fire if it's faulted
  • You don't need to capture cacheTask; the e in your callback is the same task, so you might as well use that instead. (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

这篇关于C# 5 中的异常处理和遗忘(在 .net 4.5 中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆