Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute task with the CurrentCulture set to the Task creator CurrentCulture

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?

like image 765
J4N Avatar asked Jul 29 '14 09:07

J4N


3 Answers

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?

like image 85
Yuval Itzchakov Avatar answered Nov 16 '22 00:11

Yuval Itzchakov


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.

like image 22
Mahmood Dehghan Avatar answered Nov 15 '22 23:11

Mahmood Dehghan


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
like image 1
João Simões Avatar answered Nov 16 '22 01:11

João Simões