Execute task with the CurrentCulture set to the Task creator CurrentCulture
Asked Answered
I

3

6

I've an application where we use Tasks. We also modified the cultureInfo(we use the EN-US language, but keep the date/number format), and we use .Net 4.0.

The application has a lot of thread and task, and we have a factory for the creation of Task/Threads.

For the thread, we have the following code, to ensure that every thread is launched with the correct 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
    };
}

But for the Tasks, I don't know how to implement this kind of mechanism:

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

Any idea?

Instauration answered 29/7, 2014 at 9:49 Comment(5)
What Type is TaskWorker ?Marvamarve
MonitoredTask is a custom class representing a Task(we trace them when they starts, when they finish, etc... TaskWorker is a property giving access to the Task mapped by this classInstauration
Made an error, TaskWorker is the Action that we gave in parameter of the constructor.Instauration
Though late, but best answer here: https://mcmap.net/q/135718/-is-there-a-way-of-setting-culture-for-a-whole-application-all-current-threads-and-new-threadsMehalick
@GauravSinghJantwal "and we use .Net 4.0."Instauration
B
5

Im not sure you really need a MonitoredTask for this. You can capture the custom culture using closure:

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

Another way of doing this would be to pass the current culture as object state using the proper overload (either Action<object> or Func<object, TResult>):

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

I would definitely go with the former.

For more on closure, see What are 'closures' in .NET?

Boraginaceous answered 29/7, 2014 at 10:59 Comment(1)
Well in fact, the MonitoredTask already wraps the "action", and the provided Action "TaskWorker" already makes some changes(like register that a new task has started, log any errror happening during it's execution. So I was able to set the CurrentCulture directly in this part. Sorry for the wasted time, but you pointed me to the right direction :)Instauration
E
3

From .Net 4.5, you can set a default culture for all threads in the current application domain (MSDN):

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

this way you have a unified culture for all tasks and thread in your application.

Evelunn answered 18/6, 2019 at 5:59 Comment(0)
S
1

Just to add some more detail to @Yuval Itzchakov answer, I normally create some extension methods for the TaskFactory class that preserve the Culture (I normally also add one that receives an action that sets any given property to the executing thread:

#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
Sabellian answered 29/7, 2014 at 12:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.