我可以拦截Task.Factory.StartNew吗

本文关键字:StartNew Factory Task 我可以 | 更新日期: 2023-09-27 18:19:58

我们的应用程序有很多对Task.Factory.StartNew(Action Action)的调用。不幸的是,在执行此操作时,没有设置区域性,而且没有错误处理。我从一个既能做这两件事的入门课程开始:

public static class TaskBuilder
{
    private static Action<System.Exception> _exceptionCallback;
    public static Task StartNew(Action action, CultureInfo cultureInfo, Action<System.Exception> exceptionCallback)
    {
        _exceptionCallback = exceptionCallback;
        return Task.Factory.StartNew(() =>
        {
            Thread.CurrentThread.CurrentUICulture = cultureInfo;
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
            action.Invoke();
        }).ContinueWith(t => ManageException(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
    }
    private static void ManageException(System.Exception e)
    {
        if (_exceptionCallback != null)
        {
            _exceptionCallback(e);
        }
    }
}

但后来我意识到,一个更好的方法是拦截。我想截取对StartNew的调用,以便新线程包含区域性和错误处理代码。我的尝试产生了以下代码:

public class TaskInterceptionHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        Thread.CurrentThread.CurrentUICulture = // How do I get parent cultureInfo?;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
        var methodReturn = getNext().Invoke(input, getNext);
        if (methodReturn.Exception != null)
        {
            // How do I throw the exception to the calling thread here?
        }
        return methodReturn;
    }
    public int Order { get; set; }
}

这就是我被难住的地方。首先,如何获取父级CultureInfo?第二,如何将异常返回到调用线程?以及如何在通话中使用此类?即,我如何替换现有的Task.Factor.StartNew(..)

我在使用Unity,我在这里的陌生领域。如果有任何帮助或指导,我们将不胜感激,或者有更好的解决方案吗?也许我开始走错了路?

我正在使用.NET 4.5

我在下面得到的大多数反馈似乎都避开了拦截路线。假设使用拦截器是错误的做法是否安全?如果有人能引导我朝着这个方向前进,我就可以做一个比较。如果问题的答案是肯定的,我想知道怎么做?

我可以拦截Task.Factory.StartNew吗

与其在每个任务中设置区域性,我建议您设置CultureInfo.DefaultThreadCurrentCultureCultureInfo.DefaultThreadCurrentUICulture属性,以便为未来所有线程全局设置区域性。

关于错误处理,在try/catch块中使用await可能比传递委托来处理异常更容易:

try
{
    // Task.Run is similar to Task.Factory.StartNew, but easier to use
    await Task.Run(...);
}
catch(Exception ex)
{
    // handle it...
}

顺便说一句,如果同时运行多个任务,您当前的错误处理机制将不起作用,因为所有任务只有一个_exceptionCallback。。。