Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Zarówno biblioteka środowiska uruchomieniowego języka C, jak i standardowa biblioteka języka C++ zapewniają obsługę zmiany ustawień regionalnych programu. W tym temacie omówiono problemy występujące podczas korzystania z funkcji ustawień regionalnych obu bibliotek w aplikacji wielowątkowym.
Uwagi
Za pomocą biblioteki środowiska uruchomieniowego języka C można tworzyć wielowątkowane aplikacje przy użyciu _beginthread funkcji i _beginthreadex . W tym temacie omówiono tylko aplikacje wielowątkowane utworzone przy użyciu tych funkcji. Aby uzyskać więcej informacji, zobacz _beginthread, _beginthreadex.
Aby zmienić ustawienia regionalne przy użyciu biblioteki środowiska uruchomieniowego języka C, użyj funkcji setlocale . W poprzednich wersjach programu Visual C++ta funkcja zawsze modyfikowała ustawienia regionalne w całej aplikacji. Istnieje teraz obsługa ustawiania ustawień regionalnych dla poszczególnych wątków. Odbywa się to przy użyciu funkcji _configthreadlocale . Aby określić, że właściwość setlocale powinna zmienić ustawienia regionalne tylko w bieżącym wątku, wywołaj _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) w tym wątku. Z drugiej strony wywołanie _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) spowoduje, że wątek będzie używać globalnych ustawień regionalnych, a każde wywołanie ustawianialokalnego w tym wątku spowoduje zmianę ustawień regionalnych we wszystkich wątkach, które nie zostały jawnie włączone ustawienia regionalne dla każdego wątku.
Aby zmienić ustawienia regionalne przy użyciu biblioteki środowiska uruchomieniowego języka C++, użyj klasy ustawień regionalnych. Wywołując metodę locale::global , należy zmienić ustawienia regionalne w każdym wątku, który nie włączył jawnie ustawień regionalnych dla każdego wątku. Aby zmienić ustawienia regionalne w jednym wątku lub części aplikacji, po prostu utwórz wystąpienie locale obiektu w tym wątku lub części kodu.
Uwaga
Wywoływanie ustawień regionalnych::global zmienia ustawienia regionalne zarówno dla standardowej biblioteki języka C++, jak i biblioteki środowiska uruchomieniowego języka C. Jednak wywołanie setlocale zmienia tylko ustawienia regionalne dla biblioteki środowiska uruchomieniowego języka C; biblioteka Standardowa języka C++ nie ma wpływu.
W poniższych przykładach pokazano, jak używać funkcji setlocale , klasy ustawień regionalnych i funkcji _configthreadlocale w celu zmiany ustawień regionalnych aplikacji w kilku różnych scenariuszach.
Przykład: zmienianie ustawień regionalnych z włączonymi ustawieniami regionalnymi na wątek
W tym przykładzie główny wątek powoduje zduplikowane dwa wątki podrzędne. Pierwszy wątek, Thread A, włącza ustawienia regionalne dla każdego wątku przez wywołanie ._configthreadlocale(_ENABLE_PER_THREAD_LOCALE) Drugi wątek, Thread B, a także główny wątek, nie włączaj ustawień regionalnych dla każdego wątku. Wątek A następnie przechodzi do zmiany ustawień regionalnych przy użyciu funkcji setlocale biblioteki środowiska uruchomieniowego języka C.
Ponieważ wątek A ma włączone ustawienia regionalne dla wątku, tylko funkcje biblioteki środowiska uruchomieniowego języka C w wątku A zaczynają korzystać z ustawień regionalnych "francuskich". Funkcje biblioteki środowiska uruchomieniowego języka C w wątku B i w wątku głównym nadal używają ustawień regionalnych "C". Ponadto, ponieważ setlocale nie ma wpływu na ustawienia regionalne biblioteki standardowej języka C++, wszystkie obiekty biblioteki standardowej języka C++ nadal używają ustawień regionalnych "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"
Przykład: Zmiana globalnych ustawień regionalnych z włączonymi ustawieniami regionalnymi dla każdego wątku
W tym przykładzie główny wątek powoduje zduplikowane dwa wątki podrzędne. Pierwszy wątek, Thread A, włącza ustawienia regionalne dla każdego wątku przez wywołanie ._configthreadlocale(_ENABLE_PER_THREAD_LOCALE) Drugi wątek, Thread B, a także główny wątek, nie włączaj ustawień regionalnych dla każdego wątku. Wątek A następnie przechodzi do zmiany ustawień regionalnych przy użyciu metody locale::global biblioteki standardowej języka C++.
Ponieważ wątek A ma włączone ustawienia regionalne dla wątku, tylko funkcje biblioteki środowiska uruchomieniowego języka C w wątku A zaczynają korzystać z ustawień regionalnych "francuskich". Funkcje biblioteki środowiska uruchomieniowego języka C w wątku B i w wątku głównym nadal używają ustawień regionalnych "C". Jednak ponieważ metoda locale::global zmienia ustawienia regionalne "globalnie", wszystkie obiekty biblioteki standardowej języka C++ we wszystkich wątkach zaczynają używać ustawień regionalnych "francuskich".
// 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"
Przykład: zmienianie ustawień regionalnych bez ustawień regionalnych dla wątku
W tym przykładzie główny wątek powoduje zduplikowane dwa wątki podrzędne. Pierwszy wątek, Thread A, włącza ustawienia regionalne dla każdego wątku przez wywołanie ._configthreadlocale(_ENABLE_PER_THREAD_LOCALE) Drugi wątek, Thread B, a także główny wątek, nie włączaj ustawień regionalnych dla każdego wątku. Wątek B następnie przechodzi do zmiany ustawień regionalnych przy użyciu funkcji setlocale biblioteki środowiska uruchomieniowego języka C.
Ponieważ w wątku B nie włączono ustawień regionalnych dla każdego wątku, biblioteka środowiska uruchomieniowego języka C w wątku B i w głównym wątku zaczynają korzystać z ustawień regionalnych "francuskich". Funkcje biblioteki środowiska uruchomieniowego języka C w wątku A nadal używają ustawień regionalnych "C", ponieważ wątek A ma włączone ustawienia regionalne dla wątku. Ponadto, ponieważ setlocale nie ma wpływu na ustawienia regionalne biblioteki standardowej języka C++, wszystkie obiekty biblioteki standardowej języka C++ nadal używają ustawień regionalnych "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"
Przykład: zmienianie globalnych ustawień regionalnych bez ustawień regionalnych dla każdego wątku
W tym przykładzie główny wątek powoduje zduplikowane dwa wątki podrzędne. Pierwszy wątek, Thread A, włącza ustawienia regionalne dla każdego wątku przez wywołanie ._configthreadlocale(_ENABLE_PER_THREAD_LOCALE) Drugi wątek, Thread B, a także główny wątek, nie włączaj ustawień regionalnych dla każdego wątku. Wątek B następnie przechodzi do zmiany ustawień regionalnych przy użyciu metody locale::global biblioteki standardowej języka C++.
Ponieważ w wątku B nie włączono ustawień regionalnych dla każdego wątku, biblioteka środowiska uruchomieniowego języka C w wątku B i w głównym wątku zaczynają korzystać z ustawień regionalnych "francuskich". Funkcje biblioteki środowiska uruchomieniowego języka C w wątku A nadal używają ustawień regionalnych "C", ponieważ wątek A ma włączone ustawienia regionalne dla wątku. Jednak ponieważ metoda locale::global zmienia ustawienia regionalne "globalnie", wszystkie obiekty biblioteki standardowej języka C++ we wszystkich wątkach zaczynają używać ustawień regionalnych "francuskich".
// 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"
Zobacz też
Obsługa wielowątkowości w przypadku starszego kodu (Visual C++)
_beginthread, _beginthreadex
_configthreadlocale
setlocale
Internacjonalizacja
ustawienia regionalne
<clocale>
<ustawienia regionalne>
locale, klasa