Multithreading e localidades
Tanto C tempo de execução Library e a biblioteca C++ padrão oferecem suporte para alterar a localidade do seu programa.Este tópico aborda problemas que surgem ao usar a funcionalidade de localidade das duas bibliotecas em um aplicativo multithreaded.
Comentários
Com o C tempo de execução biblioteca, você pode criar aplicativos multithread usando o _beginthread e _beginthreadex funções. Este tópico aborda somente aplicativos multissegmentados criados usando essas funções.Para obter mais informações, consulte _beginthread, _beginthreadex.
Para alterar a localidade usando a biblioteca de tempo de execução C, use o setLocale função. Nas versões anteriores do Visual C++, essa função sempre seria modificar o localidade em todo o aplicativo. Há agora suporte para definir a localidade em uma base por thread.Isso é concluído usando o _configthreadlocale função. Para especificar que setLocale só deve alterar a localidade do thread corrente, telefonar _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) Esse segmento. Por outro lado, telefonar _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) fará com que esse thread para usar a localidade global e qualquer telefonar para setLocale Esse thread irá alterar a localidade em todos os threads que não tenha habilitado explicitamente por thread local.
Para alterar a localidade usando C++ tempo de execução biblioteca, use o localidade Classe. Chamando o Localidade::global método, você alterar a localidade de todos os threads que não tem habilitado explicitamente por thread local. Para alterar a localidade em um único thread ou parte de um aplicativo, basta criar uma instância de um locale objeto em que thread ou parte do código.
Observação: |
---|
Chamada Localidade::global Altera a localidade para a biblioteca C++ padrão e o C tempo de execução Library. No entanto, chamar setLocale apenas altera a localidade para o C tempo de execução Library; a biblioteca C++ padrão não é afetado. |
Os exemplos a seguir mostram como usar o setLocale função, o localidade Classee o _configthreadlocale função para alterar a localidade de um aplicativo em vários cenários diferentes.
Exemplo
Neste exemplo, o thread principal gera dois segmentos filhos.O primeiro thread, o Thread A, permite por thread local, chamada _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Segundo thread, o Thread B, bem sistema autônomo o thread principal, não ative a localidade por thread.O thread A e, em seguida, continua para alterar a localidade usando o setLocale função de biblioteca C tempo de execução Library.
Desde o Thread A por thread local permitiu, apenas as funções da C tempo de execução biblioteca no thread um início usando a localidade "Francês".As funções da C tempo de execução biblioteca no Thread B e no thread principal continuam a usar a localidade "C".Além disso, desde setLocalenão afeta a C++ Standard Library localidade, todos os objetos da biblioteca C++ padrão continuam a usar a localidade "C".
// multithread_locale_1.cpp
// compile with: /EHsc /MD
#include <clocale>
#include <cstdio>
#include <locale>
#include <process.h>
#include <windows.h>
#define NUM_THREADS 2
using namespace std;
unsigned __stdcall RunThreadA(void *params);
unsigned __stdcall RunThreadB(void *params);
BOOL localeSet = FALSE;
HANDLE printMutex = CreateMutex(NULL, FALSE, NULL);
int main()
{
HANDLE threads[NUM_THREADS];
unsigned aID;
threads[0] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadA, NULL, 0, &aID);
unsigned bID;
threads[1] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadB, NULL, 0, &bID);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
printf_s("[Thread main] Per-thread locale is NOT enabled.\n");
printf_s("[Thread main] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread main] locale::global is set to \"%s\"\n",
locale().name().c_str());
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(printMutex);
return 0;
}
unsigned __stdcall RunThreadA(void *params)
{
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
setlocale(LC_ALL, "french");
localeSet = TRUE;
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread A] Per-thread locale is enabled.\n");
printf_s("[Thread A] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread A] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
unsigned __stdcall RunThreadB(void *params)
{
while (!localeSet)
Sleep(100);
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread B] Per-thread locale is NOT enabled.\n");
printf_s("[Thread B] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread B] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
[Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "French_France.1252" [Thread A] locale::global is set to "C" [Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "C" [Thread B] locale::global is set to "C" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "C" [Thread main] locale::global is set to "C"
Neste exemplo, o thread principal gera dois segmentos filhos.O primeiro thread, o Thread A, permite por thread local, chamada _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Segundo thread, o Thread B, bem sistema autônomo o thread principal, não ative a localidade por thread.O thread A e, em seguida, continua para alterar a localidade usando o Localidade::global método de biblioteca C++ padrão.
Desde o Thread A por thread local permitiu, apenas as funções da C tempo de execução biblioteca no thread um início usando a localidade "Francês".As funções da C tempo de execução biblioteca no Thread B e no thread principal continuam a usar a localidade "C".No entanto, como a Localidade::globalmétodo altera a localidade "global", todos os objetos da biblioteca C++ padrão todos os threads começar a usar a localidade "Francês".
// multithread_locale_2.cpp
// compile with: /EHsc /MD
#include <clocale>
#include <cstdio>
#include <locale>
#include <process.h>
#include <windows.h>
#define NUM_THREADS 2
using namespace std;
unsigned __stdcall RunThreadA(void *params);
unsigned __stdcall RunThreadB(void *params);
BOOL localeSet = FALSE;
HANDLE printMutex = CreateMutex(NULL, FALSE, NULL);
int main()
{
HANDLE threads[NUM_THREADS];
unsigned aID;
threads[0] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadA, NULL, 0, &aID);
unsigned bID;
threads[1] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadB, NULL, 0, &bID);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
printf_s("[Thread main] Per-thread locale is NOT enabled.\n");
printf_s("[Thread main] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread main] locale::global is set to \"%s\"\n",
locale().name().c_str());
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(printMutex);
return 0;
}
unsigned __stdcall RunThreadA(void *params)
{
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
locale::global(locale("french"));
localeSet = TRUE;
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread A] Per-thread locale is enabled.\n");
printf_s("[Thread A] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread A] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
unsigned __stdcall RunThreadB(void *params)
{
while (!localeSet)
Sleep(100);
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread B] Per-thread locale is NOT enabled.\n");
printf_s("[Thread B] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread B] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
[Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "French_France.1252" [Thread A] locale::global is set to "French_France.1252" [Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "C" [Thread B] locale::global is set to "French_France.1252" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "C" [Thread main] locale::global is set to "French_France.1252"
Neste exemplo, o thread principal gera dois segmentos filhos.O primeiro thread, o Thread A, permite por thread local, chamada _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Segundo thread, o Thread B, bem sistema autônomo o thread principal, não ative a localidade por thread.O thread B, em seguida, continua a alterar a localidade usando o setLocale função de biblioteca C tempo de execução Library.
Como B de thread não tem por thread local ativado, as funções da C tempo de execução biblioteca no Thread B e no thread principal começar a usar a localidade "Francês".As funções C tempo de execução biblioteca continuar Thread A usar a localidade "C" porque o Thread A possui por thread local habilitado.Além disso, desde setLocalenão afeta a C++ Standard Library localidade, todos os objetos da biblioteca C++ padrão continuam a usar a localidade "C".
// multithread_locale_3.cpp
// compile with: /EHsc /MD
#include <clocale>
#include <cstdio>
#include <locale>
#include <process.h>
#include <windows.h>
#define NUM_THREADS 2
using namespace std;
unsigned __stdcall RunThreadA(void *params);
unsigned __stdcall RunThreadB(void *params);
BOOL localeSet = FALSE;
BOOL configThreadLocaleCalled = FALSE;
HANDLE printMutex = CreateMutex(NULL, FALSE, NULL);
int main()
{
HANDLE threads[NUM_THREADS];
unsigned aID;
threads[0] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadA, NULL, 0, &aID);
unsigned bID;
threads[1] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadB, NULL, 0, &bID);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
printf_s("[Thread main] Per-thread locale is NOT enabled.\n");
printf_s("[Thread main] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread main] locale::global is set to \"%s\"\n",
locale().name().c_str());
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(printMutex);
return 0;
}
unsigned __stdcall RunThreadA(void *params)
{
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
configThreadLocaleCalled = TRUE;
while (!localeSet)
Sleep(100);
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread A] Per-thread locale is enabled.\n");
printf_s("[Thread A] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread A] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
unsigned __stdcall RunThreadB(void *params)
{
while (!configThreadLocaleCalled)
Sleep(100);
setlocale(LC_ALL, "french");
localeSet = TRUE;
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread B] Per-thread locale is NOT enabled.\n");
printf_s("[Thread B] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread B] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
[Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "French_France.1252" [Thread B] locale::global is set to "C" [Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "C" [Thread A] locale::global is set to "C" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "French_France.1252" [Thread main] locale::global is set to "C"
Neste exemplo, o thread principal gera dois segmentos filhos.O primeiro thread, o Thread A, permite por thread local, chamada _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Segundo thread, o Thread B, bem sistema autônomo o thread principal, não ative a localidade por thread.O thread B, em seguida, continua a alterar a localidade usando o Localidade::global método de biblioteca C++ padrão.
Como B de thread não tem por thread local ativado, as funções da C tempo de execução biblioteca no Thread B e no thread principal começar a usar a localidade "Francês".As funções C tempo de execução biblioteca continuar Thread A usar a localidade "C" porque o Thread A possui por thread local habilitado.No entanto, como a Localidade::globalmétodo altera a localidade "global", todos os objetos da biblioteca C++ padrão todos os threads começar a usar a localidade "Francês".
// multithread_locale_4.cpp
// compile with: /EHsc /MD
#include <clocale>
#include <cstdio>
#include <locale>
#include <process.h>
#include <windows.h>
#define NUM_THREADS 2
using namespace std;
unsigned __stdcall RunThreadA(void *params);
unsigned __stdcall RunThreadB(void *params);
BOOL localeSet = FALSE;
BOOL configThreadLocaleCalled = FALSE;
HANDLE printMutex = CreateMutex(NULL, FALSE, NULL);
int main()
{
HANDLE threads[NUM_THREADS];
unsigned aID;
threads[0] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadA, NULL, 0, &aID);
unsigned bID;
threads[1] = (HANDLE)_beginthreadex(
NULL, 0, RunThreadB, NULL, 0, &bID);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
printf_s("[Thread main] Per-thread locale is NOT enabled.\n");
printf_s("[Thread main] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread main] locale::global is set to \"%s\"\n",
locale().name().c_str());
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(printMutex);
return 0;
}
unsigned __stdcall RunThreadA(void *params)
{
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
configThreadLocaleCalled = TRUE;
while (!localeSet)
Sleep(100);
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread A] Per-thread locale is enabled.\n");
printf_s("[Thread A] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread A] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
unsigned __stdcall RunThreadB(void *params)
{
while (!configThreadLocaleCalled)
Sleep(100);
locale::global(locale("french"));
localeSet = TRUE;
WaitForSingleObject(printMutex, INFINITE);
printf_s("[Thread B] Per-thread locale is NOT enabled.\n");
printf_s("[Thread B] CRT locale is set to \"%s\"\n",
setlocale(LC_ALL, NULL));
printf_s("[Thread B] locale::global is set to \"%s\"\n\n",
locale().name().c_str());
ReleaseMutex(printMutex);
return 1;
}
[Thread B] Per-thread locale is NOT enabled. [Thread B] CRT locale is set to "French_France.1252" [Thread B] locale::global is set to "French_France.1252" [Thread A] Per-thread locale is enabled. [Thread A] CRT locale is set to "C" [Thread A] locale::global is set to "French_France.1252" [Thread main] Per-thread locale is NOT enabled. [Thread main] CRT locale is set to "French_France.1252" [Thread main] locale::global is set to "French_France.1252"