【问题标题】:Execute task with the CurrentCulture set to the Task creator CurrentCulture将 CurrentCulture 设置为任务创建者 CurrentCulture 执行任务
【发布时间】:2014-07-29 09:49:54
【问题描述】:

我有一个使用任务的应用程序。我们还修改了cultureInfo(我们使用EN-US语言,但保留日期/数字格式),我们使用.Net 4.0。

应用程序有很多线程和任务,我们有一个创建任务/线程的工厂。

对于线程,我们有以下代码,以确保使用正确的 CurrentCulture 启动每个线程:

//This is basically only the constructor, but it describe well how we create the Thread:
public MonitoredThread(ThreadStart threadStart, string name, bool isBackground = false)
{
    m_threadStart = threadStart;
    m_name = name;
    m_isBackground = isBackground;
    Thread = new Thread(ThreadWorker)
    {
        Name = name,
        IsBackground = isBackground,
        CurrentCulture = CustomCultureInfo.CurrentCulture,
        CurrentUICulture = CustomCultureInfo.CurrentCulture
    };
}

但是对于Tasks,我不知道如何实现这种机制:

public static Task ExecuteTask(Action action, string name)
{
    MonitoredTask task = new MonitoredTask(action, name);
    return Task.Factory.StartNew(task.TaskWorker);
}

有什么想法吗?

【问题讨论】:

  • TaskWorker 是什么类型?
  • MonitoredTask 是一个代表Task 的自定义类(我们在它们开始、结束等时跟踪它们...TaskWorker 是一个属性,可以访问映射的Task按此类
  • 出错了,TaskWorker是我们在构造函数的参数中给的Action。
  • 虽然晚了,但最好的答案在这里:stackoverflow.com/a/7536117/1662459
  • @GauravSinghJantwal “我们使用 .Net 4.0。”

标签: c# .net multithreading task-parallel-library cultureinfo


【解决方案1】:

我不确定您是否真的需要 MonitoredTask。您可以使用闭包捕获自定义文化:

public static Task ExecuteTask(Action action, string name)
{
   var customCulture = CustomCultureInfo.CurrentCulture;
   return Task.Factory.StartNew(() => 
   {
       // use customCulture variable as needed
      // inside the generated task.
   });
}

另一种方法是使用适当的重载(Action<object>Func<object, TResult>)将当前文化作为 object state 传递:

public static Task ExecuteTask(Action action, string name)
{
   var customCulture = CustomCultureInfo.CurrentCulture;
   return Task.Factory.StartNew((obj) => 
   {
       var culture = (CultureInfo) obj;
       // use customCulture variable as needed
      // inside the generated task.
   }, customCulture);
}

我肯定会选择前者。

有关关闭的更多信息,请参阅What are 'closures' in .NET?

【讨论】:

  • 事实上,MonitoredTask 已经包装了“动作”,并且提供的动作“TaskWorker”已经进行了一些更改(比如注册一个新任务已经开始,记录它执行过程中发生的任何错误。所以我可以直接在这部分设置 CurrentCulture。很抱歉浪费了时间,但你指出了正确的方向:)
【解决方案2】:

从 .Net 4.5 开始,您可以为当前应用程序域 (MSDN) 中的所有线程设置默认区域性:

CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

这样您就可以为应用程序中的所有任务和线程建立统一的文化。

【讨论】:

    【解决方案3】:

    只是为了向@Yuval Itzchakov 答案添加更多细节,我通常为TaskFactory 类创建一些扩展方法来保留文化(我通常还会添加一个接收将任何给定属性设置到执行线程的操作的方法:

    #region StartNewWithPersistedCulture methods
    
    public static Task<TResult> StartNewWithPersistedCulture<TResult>(
        this TaskFactory taskFactory, Func<TResult> function, CancellationToken cancellationToken = default (CancellationToken), TaskCreationOptions creationOptions = default (TaskCreationOptions))
    {
        if (taskFactory == null) throw new ArgumentNullException("taskFactory");
        if (function == null) throw new ArgumentNullException("function");
    
        var currentCulture = Thread.CurrentThread.CurrentCulture;
        var currentUICulture = Thread.CurrentThread.CurrentUICulture;
        return taskFactory.StartNew(
            () =>
            {
                Thread.CurrentThread.CurrentCulture = currentCulture;
                Thread.CurrentThread.CurrentUICulture = currentUICulture;
    
                return function();
            }, cancellationToken, creationOptions, TaskScheduler.Default);
    }
    
    public static Task StartNewWithPersistedCulture(
        this TaskFactory taskFactory, Action action, CancellationToken cancellationToken = default (CancellationToken), TaskCreationOptions creationOptions = default (TaskCreationOptions))
    {
        if (taskFactory == null) throw new ArgumentNullException("taskFactory");
        if (action == null) throw new ArgumentNullException("action");
    
        var currentCulture = Thread.CurrentThread.CurrentCulture;
        var currentUICulture = Thread.CurrentThread.CurrentUICulture;
        return taskFactory.StartNew(
            () =>
            {
                Thread.CurrentThread.CurrentCulture = currentCulture;
                Thread.CurrentThread.CurrentUICulture = currentUICulture;
    
                action();
            }, cancellationToken, creationOptions, TaskScheduler.Default);
    } 
    
    #endregion
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多