Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Tanto a C Runtime Library quanto a C++ Standard Library fornecem suporte para alterar a localidade do seu programa. Este tópico discute problemas que surgem ao usar a funcionalidade de localidade de ambas as bibliotecas em um aplicativo multithreaded.
Observações
Com a Biblioteca Runtime C, pode-se criar aplicações multithreaded usando as funções _beginthread e _beginthreadex. Este tópico aborda apenas aplicativos multithreaded criados usando essas funções. Para obter mais informações, consulte _beginthread, _beginthreadex.
Para alterar a localidade usando a C Runtime Library, use a função setlocale . Em versões anteriores do Visual C++, essa função sempre modificava a localidade em todo o aplicativo. Agora há suporte para definir a localidade por thread. Isso é feito usando a função _configthreadlocale . Para especificar que setlocale só deve alterar a localidade no thread atual, faça a chamada de _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) nesse thread. Por outro lado, a chamada _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) fará com que esse thread use a localidade global, e qualquer chamada para setlocale nesse thread alterará a localidade em todos os threads que não habilitaram explicitamente a localidade por thread.
Para alterar a localidade usando a biblioteca de tempo de execução C++, use a classe de localidade. Ao chamar o método locale::global , você altera a localidade em cada thread que não habilitou explicitamente a localidade por thread. Para alterar a localidade em um único thread ou parte de um aplicativo, basta criar uma instância de um locale objeto nesse thread ou parte do código.
Observação
Chamar locale::global altera a localidade da Biblioteca Padrão C++ e da Biblioteca de Tempo de Execução C. No entanto, chamar setlocale só altera a localidade para a C Runtime Library; a biblioteca padrão C++ não é afetada.
Os exemplos a seguir mostram como usar a função setlocale , a classe locale e a função _configthreadlocale para alterar a localidade de um aplicativo em vários cenários diferentes.
Exemplo: alterar a configuração regional com localidade por thread ativada
Neste exemplo, a thread principal gera duas threads filhas. O primeiro thread, Thread A, habilita a localidade por thread chamando _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). O segundo thread, Thread B, bem como o thread principal, não habilitam a localidade por thread. Em seguida, o thread A prossegue para alterar a localidade usando a função setlocale da C Runtime Library.
Como o Thread A tem a localidade por thread habilitada, somente as funções da Biblioteca de Tempo de Execução C no Thread A começam a usar a localidade "francesa". As funções C Runtime Library no Thread B e no thread principal continuam a usar a localidade "C". Além disso, como setlocale não afeta a localidade C++ Standard Library, todos os objetos C++ Standard Library 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"
Exemplo: alterar localidade global com localidade por thread ativada
Neste exemplo, a thread principal gera duas threads filhas. O primeiro thread, Thread A, habilita a localidade por thread chamando _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). O segundo thread, Thread B, bem como o thread principal, não habilitam a localidade por thread. Em seguida, o thread A prossegue para alterar a localidade usando o método locale::global da Biblioteca Padrão C++.
Como o Thread A tem a localidade por thread habilitada, somente as funções da Biblioteca de Tempo de Execução C no Thread A começam a usar a localidade "francesa". As funções C Runtime Library no Thread B e no thread principal continuam a usar a localidade "C". No entanto, como o método locale::global altera a localidade "globalmente", todos os objetos C++ Standard Library em todos os threads começam a usar a localidade "french".
// 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"
Exemplo: Alterar a configuração regional sem ter a configuração regional por thread ativada
Neste exemplo, a thread principal gera duas threads filhas. O primeiro thread, Thread A, habilita a localidade por thread chamando _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). O segundo thread, Thread B, bem como o thread principal, não habilitam a localidade por thread. Em seguida, o Thread B prossegue para alterar a localidade usando a função setlocale da C Runtime Library.
Como o Thread B não tem a localidade por thread habilitada, as funções da Biblioteca de Tempo de Execução C no Thread B e no thread principal começam a usar a localidade "francesa". As funções da Biblioteca de Tempo de Execução C no Thread A continuam a usar a localidade "C" porque o Thread A tem a localidade por thread habilitada. Além disso, como setlocale não afeta a localidade C++ Standard Library, todos os objetos C++ Standard Library 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"
Exemplo: Alterar localidade global sem localidade por thread habilitada
Neste exemplo, a thread principal gera duas threads filhas. O primeiro thread, Thread A, habilita a localidade por thread chamando _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). O segundo thread, Thread B, bem como o thread principal, não habilitam a localidade por thread. Em seguida, o Thread B prossegue para alterar a localidade usando o método locale::global da Biblioteca Padrão C++.
Como o Thread B não tem a localidade por thread habilitada, as funções da Biblioteca de Tempo de Execução C no Thread B e no thread principal começam a usar a localidade "francesa". As funções da Biblioteca de Tempo de Execução C no Thread A continuam a usar a localidade "C" porque o Thread A tem a localidade por thread habilitada. No entanto, como o método locale::global altera a localidade "globalmente", todos os objetos C++ Standard Library em todos os threads começam a usar a localidade "french".
// 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"
Ver também
Suporte a multithreading para código mais antigo (Visual C++)
_beginthread, _beginthreadex
_configthreadlocale
setlocale
Internacionalização
Localidade
<Clocale>
<localidade>
Classe de localidade