本文介绍了Thread.CurrentThread.CurrentCulture不是在一个线程的工作线程池,里面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个将被称为一个线程内,这些线程由线程池管理方法。
的方法是调用DLL的方法,不幸的是需要被正确地执行一个特定的语言环境。



思想促进这种方法之前,要由线程池跑了,我已经测试它,而在应用程序的主线程中运行,也当我手动管理线程,它工作正常,但是当我把它变成工作线程池里面,不适用的语言环境,因此该方法不正确的行为。



下面是应由语言环境变化的影响(但不表现良好)的方法的部分:

 的CultureInfo之前= Thread.CurrentThread.CurrentCulture; 

Thread.CurrentThread.CurrentCulture =新的CultureInfo(FA-IR);
INT结果= tsms.SendSMS(smsTask.MobileNumber.MobileNumberInString,smsTask.Message);
Thread.CurrentThread.CurrentUICulture =前;

和这里的线程池创建结构:

 的foreach(sMSTask smsTask在tasksList)
{
如果(this.threadsCount< this.threadPoolSize)
{
this.threadsCount ++ ;
ThreadPool.QueueUserWorkItem(新WaitCallback(SendMessage函数),(对象)smsTask);
}
}



我也尝试设置区域设置线程对象像下面,但它并没有解决这个问题:
(2号线和3):

  threadObject =新主题(新的ThreadStart (TaskProcessingThreadFunction)); 
threadObject.CurrentCulture =新的CultureInfo(FA-IR);
threadObject.CurrentUICulture =新的CultureInfo(FA-IR);
threadObject.Start();

请指导我,我应该如何得到正确的结果,而这种方法正在运行的内部线程池。



更新版本:

  this.isTerminated = FALSE; 
Thread.sleep代码(1000);
,而
{
Thread.sleep代码(1000)(this.isTerminated!);
&IList的LT; SMSTask> tasksList = dataProvider.GetTasks(this.minimumRetryTimeInSeconds);

如果(tasksList == NULL || tasksList.Count< 1)
继续;
singleTaskConsoleObject(+ tasksList.Count +任务(S)获取用于发送);

变种cultureToUse =新System.Globalization.CultureInfo(FA-IR);
VAR currentThread = System.Threading.Thread.CurrentThread;
currentThread.CurrentCulture = cultureToUse;
currentThread.CurrentUICulture = cultureToUse;

VAR currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
的foreach(SMSTask smsTask在tasksList)
{
如果(this.threadsCount< this.threadPoolSize)
{
this.threadsCount ++;
smsTask.Iden = currentIdentity;
ThreadPool.QueueUserWorkItem(新WaitCallback(SendMessage函数),(对象)smsTask);
}
}
而(this.threadsCount大于0)
Thread.sleep代码(50);
}

其他方法:

 私人无效SendMessage函数(对象smsTask)
{
System.Security.Principal.WindowsImpersonationContext impersonationContext = NULL;

{
SMSTask smsTaskEntity =(SMSTask)smsTask;
impersonationContext =((System.Security.Principal.WindowsIdentity)(smsTaskEntity.Iden))模仿();

SmsSender smsSender =新SmsSender();
SMSSendingResponse响应= smsSender.SendSMS(smsTaskEntity);
布尔loggingResult = dataProvider.UpdateResponse(响应);
singleTaskGridObject(响应,loggingResult);

this.threadsCount--;
}
终于
{
如果(impersonationContext!= NULL)
{
impersonationContext.Undo();
}
}
}

和这个单独的类:

 公共SMSSendingResponse SendSMS(sMSTask smsTask)
{

TSMSLIB_TLB.TSMS_Tooba TSMS =新TSMS_Tooba ();

SendingResult sendingResult = SendingResult.Initial_Condition;

{

System.Globalization.CultureInfo之前= System.Threading.Thread.CurrentThread.CurrentCulture;

System.Threading.Thread.CurrentThread.CurrentCulture =
新System.Globalization.CultureInfo(FA-IR);

弦乐味精=的String.Format(System.Threading.Thread.CurrentThread.CurrentCulture,smsTask.Message);

INT结果= tsms.SendSMS(smsTask.MobileNumber.MobileNumberInString,味精);
System.Threading.Thread.CurrentThread.CurrentUICulture =前;
如果(结果大于0)
{
返回新SMSSendingResponse(smsTask,SMSDeclarations.SendingStatus.SentSuccessfully,result.ToString());
}
,否则
{
的foreach(SendingResult sResult在Enum.GetValues(typeof运算(SendingResult)))
{
如果(结果==(INT )sResult)
{
sendingResult = sResult;
}
}
返回新SMSSendingResponse(smsTask,SMSDeclarations.SendingStatus.SendingFailed,
result.ToString(),sendingResult.ToString());
}
}
赶上(异常前)
{
返回新SMSSendingResponse(smsTask,SMSDeclarations.SendingStatus.SendingFailed,
0​​的ToString( ),异常发生);
}

}


解决方案

文化必须由线程调用的实际方法中得到应用。



有一个简单的方法应该是包裹方法里面,从线程入队前的工作,线程池中的线程应用CultureInfo的另一种方法的线程池来执行在执行原来的方法,类似;

 私有静态WaitCallback PropagateCulture(WaitCallback动作)
{
变种的CurrentCulture = Thread.CurrentThread.CurrentCulture;
变种的CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
则返回(x)=>
{
Thread.CurrentThread.CurrentCulture =的CurrentCulture;
Thread.CurrentThread.CurrentUICulture =的CurrentUICulture;
动作(X);
};
}



由于这种方法,你只用提交给线程池;



  ThreadPool.QueueUserWorkItem(PropagateCulture(SendMessage函数),(对象)smsTask); 



(感谢Aidiakapi您指出 WaitCallback 在下面的评论)


I have a method which will be called inside a thread and those threads are managed by threadpool.The method is calling a DLL's method which unfortunately requires a specific locale for being performed correctly.

Before puting this method to be ran by threadpool, I've tested it while running in application's main thread and also while I manually manage the threads and it works fine, but when I put it into work inside a threadpool, locale is not applied and consequently the method does not behave correctly.

Here is the part of the method which should be affected by locale change (but not behave well):

CultureInfo before = Thread.CurrentThread.CurrentCulture;

Thread.CurrentThread.CurrentCulture = new CultureInfo("fa-IR");
int result = tsms.SendSMS(smsTask.MobileNumber.MobileNumberInString, smsTask.Message);
Thread.CurrentThread.CurrentUICulture = before;

and here is the threadpool creating structure:

foreach (SMSTask smsTask in tasksList)
{
    if (this.threadsCount < this.threadPoolSize)
    {
        this.threadsCount++;
        ThreadPool.QueueUserWorkItem(new WaitCallback(SendMessage), (object)smsTask);
    }
}

I also tried setting locale to thread object like below but it didn't solve the problem:(line 2 and 3):

threadObject = new Thread(new ThreadStart(TaskProcessingThreadFunction));
threadObject.CurrentCulture = new CultureInfo("fa-IR");
threadObject.CurrentUICulture = new CultureInfo("fa-IR");
threadObject.Start();

Please guide me on how should I get the correct result while this method is being ran inside threadpool.

Updated Version:

this.isTerminated = false;
            Thread.Sleep(1000);
            while (!this.isTerminated)
            {
                Thread.Sleep(1000);
                IList<SMSTask> tasksList = dataProvider.GetTasks(this.minimumRetryTimeInSeconds);

                if (tasksList == null || tasksList.Count < 1)
                    continue;
                singleTaskConsoleObject(" " + tasksList.Count + " task(s) fetched for sending.");

                var cultureToUse = new System.Globalization.CultureInfo("fa-IR");
                var currentThread = System.Threading.Thread.CurrentThread;
                currentThread.CurrentCulture = cultureToUse;
                currentThread.CurrentUICulture = cultureToUse;

                var currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
                foreach (SMSTask smsTask in tasksList)
                {
                    if (this.threadsCount < this.threadPoolSize)
                    {
                        this.threadsCount++;
                        smsTask.Iden = currentIdentity;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(SendMessage), (object)smsTask);
                    }
                }
                while (this.threadsCount > 0)
                    Thread.Sleep(50);
            }

Other Methods:

private void SendMessage(object smsTask)
        {
            System.Security.Principal.WindowsImpersonationContext impersonationContext = null;
            try
            {
                SMSTask smsTaskEntity = (SMSTask)smsTask;
                impersonationContext = ((System.Security.Principal.WindowsIdentity)(smsTaskEntity.Iden)).Impersonate();

                SmsSender smsSender = new SmsSender();
                SMSSendingResponse response = smsSender.SendSMS(smsTaskEntity);
                bool loggingResult = dataProvider.UpdateResponse(response);
                singleTaskGridObject(response, loggingResult);

                this.threadsCount--;
            }
            finally
            {
                if (impersonationContext != null)
                {
                    impersonationContext.Undo();
                }
            }
        }

And this separate class:

public SMSSendingResponse SendSMS(SMSTask smsTask)
{

        TSMSLIB_TLB.TSMS_Tooba tsms = new TSMS_Tooba();

        SendingResult sendingResult = SendingResult.Initial_Condition;
        try
        {

            System.Globalization.CultureInfo before = System.Threading.Thread.CurrentThread.CurrentCulture;

            System.Threading.Thread.CurrentThread.CurrentCulture =
                new System.Globalization.CultureInfo("fa-IR");

            string msg = string.Format(System.Threading.Thread.CurrentThread.CurrentCulture, smsTask.Message);

            int result = tsms.SendSMS(smsTask.MobileNumber.MobileNumberInString, msg);
            System.Threading.Thread.CurrentThread.CurrentUICulture = before;
            if (result > 0)
            {
                return new SMSSendingResponse(smsTask, SMSDeclarations.SendingStatus.SentSuccessfully, result.ToString());
            }
            else
            {
                foreach (SendingResult sResult in Enum.GetValues(typeof(SendingResult)))
                {
                    if (result == (int)sResult)
                    {
                        sendingResult = sResult;
                    }
                }
                return new SMSSendingResponse(smsTask, SMSDeclarations.SendingStatus.SendingFailed,
                    result.ToString(), sendingResult.ToString());
            }
        }
        catch (Exception ex)
        {
            return new SMSSendingResponse(smsTask, SMSDeclarations.SendingStatus.SendingFailed,
                    "0".ToString(), "Exception occured");
        }

    }
解决方案

The culture must be applied inside the actual method called by the thread.

A simple way should be to wrap the method to be executed on the thread pool inside another method that applies the CultureInfo from the thread enqueuing the job to the thread pool thread before executing the original method, something like;

private static WaitCallback PropagateCulture(WaitCallback action)
{
    var currentCulture   = Thread.CurrentThread.CurrentCulture;
    var currentUiCulture = Thread.CurrentThread.CurrentUICulture;
    return (x) =>
    {
        Thread.CurrentThread.CurrentCulture   = currentCulture;
        Thread.CurrentThread.CurrentUICulture = currentUiCulture;
        action(x);
    };
}

Given that method, you just submit to the threadpool using;

ThreadPool.QueueUserWorkItem(PropagateCulture(SendMessage), (object)smsTask);

(thanks to Aidiakapi for pointing out WaitCallback in the comments below)

这篇关于Thread.CurrentThread.CurrentCulture不是在一个线程的工作线程池,里面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 19:44