Udostępnij za pośrednictwem


Wielowątkowość i ustawienia regionalne

Standardowa biblioteka języka C++ i biblioteka C Runtime Library zapewniają obsługę zmiany ustawień regionalnych programu.W tym temacie omówiono problemy, które występują podczas korzystania z funkcji ustawień regionalnych obu bibliotek w aplikacji wielowątkowych.

Uwagi

C Runtime Library umożliwia tworzenie aplikacji wielowątkowych za pomocą _beginthread i _beginthreadex funkcji.W tym temacie omówiono tylko aplikacje wielowątkowe utworzone za pomocą tych funkcji.Aby uzyskać dodatkowe informacje, zobacz _beginthread, _beginthreadex.

Aby zmienić ustawienia regionalne, używając biblioteka C Runtime Library, użyj setlocale funkcji.W poprzednich wersjach programu Visual C++, ta funkcja zawsze mogą modyfikować ustawienia regionalne w całej całej aplikacji.Istnieje teraz obsługę ustawienia regionalne na zasadzie na wątek.Odbywa się za pomocą _configthreadlocale funkcji.Aby określić, że setlocale tylko należy zmienić ustawienia regionalne w bieżącym wątku, wywołanie _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) w tym wątku.I odwrotnie, wywołanie _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) spowoduje, że wątek do użytku globalnego ustawienia regionalne, a każde wywołanie setlocale w tym wątku spowoduje zmianę ustawień regionalnych w wszystkie wątki, które nie zostały jawnie włączone ustawień regionalnych na wątek.

Aby zmienić ustawienia regionalne, używając języka C++ Runtime Library, użyj locale — Klasa.Wywołując locale::global metoda, należy zmienić ustawienia regionalne w każdym wątku, który nie włączył jawnie ustawień regionalnych na wątek.Aby zmienić ustawienia regionalne w pojedynczym wątku lub część aplikacji, po prostu utworzyć wystąpienia locale obiekt w tym wątku lub fragment kodu.

[!UWAGA]

Wywołanie locale::global zmienia ustawienia regionalne dla standardowa biblioteka języka C++ i biblioteka C Runtime Library.Jednak wywoływania setlocale zmienia ustawienia regionalne tylko dla C Runtime Library; Standardowa biblioteka języka C++ pozostanie niezmieniona.

Następujące przykłady przedstawiają metody korzystania setlocale funkcji, locale — Klasai _configthreadlocale funkcji, aby zmienić ustawienia regionalne aplikacji w przypadku różnych scenariuszy.

Przykład

W tym przykładzie głównego wątku ikra dwóch wątków podrzędnych.Pierwszy wątku, wątek A, włącza ustawienia regionalne na wątek poprzez wywołanie _configthreadlocale(_ENABLE_PER_THREAD_LOCALE).Drugi wątek, B wątku, a także głównego wątku, nie należy włączać ustawień regionalnych na wątek.Wątek wtedy przechodzi do zmiany ustawień regionalnych, przy użyciu setlocale funkcja biblioteka C Runtime Library.

Ponieważ wątek A ma włączone, regionalnych na wątek tylko funkcje C Runtime Library w wątku A uruchamiania przy użyciu locale "francuskie".Funkcje C Runtime Library w wątku B i w głównym wątku w dalszym ciągu używać ustawień regionalnych "C".Ponadto, od setlocale nie wpływa na ustawienia regionalne standardowa biblioteka języka C++, wszystkie standardowa biblioteka języka C++ obiekty w dalszym ciągu używać 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;
}
  

W tym przykładzie głównego wątku ikra dwóch wątków podrzędnych.Pierwszy wątku, wątek A, włącza ustawienia regionalne na wątek poprzez wywołanie _configthreadlocale(_ENABLE_PER_THREAD_LOCALE).Drugi wątek, B wątku, a także głównego wątku, nie należy włączać ustawień regionalnych na wątek.Wątek wtedy przechodzi do zmiany ustawień regionalnych, przy użyciu locale::global metoda standardowa biblioteka języka C++.

Ponieważ wątek A ma włączone, regionalnych na wątek tylko funkcje C Runtime Library w wątku A uruchamiania przy użyciu locale "francuskie".Funkcje C Runtime Library w wątku B i w głównym wątku w dalszym ciągu używać ustawień regionalnych "C".Jednakże, ponieważ locale::global metoda zmienia ustawienia regionalne "globalny", wszystkie obiekty standardowa biblioteka języka C++ w wszystkie wątki rozpocząć korzystanie z narzędzia locale "francuskie".

// 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;
}
  

W tym przykładzie głównego wątku ikra dwóch wątków podrzędnych.Pierwszy wątku, wątek A, włącza ustawienia regionalne na wątek poprzez wywołanie _configthreadlocale(_ENABLE_PER_THREAD_LOCALE).Drugi wątek, B wątku, a także głównego wątku, nie należy włączać ustawień regionalnych na wątek.Wątek B, a następnie przechodzi do zmiany ustawień regionalnych, przy użyciu setlocale funkcja biblioteka C Runtime Library.

Od wątku B nie ma włączone ustawienia regionalne na wątek, funkcje C Runtime Library w wątku B i w głównym wątku uruchomiony przy użyciu locale "francuskie".Funkcje C Runtime Library w wątku A Kontynuuj, aby użyć ustawień regionalnych "C", ponieważ wątek A ma włączone ustawienia regionalne na wątek.Ponadto, od setlocale nie wpływa na ustawienia regionalne standardowa biblioteka języka C++, wszystkie standardowa biblioteka języka C++ obiekty w dalszym ciągu używać 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;
}
  

W tym przykładzie głównego wątku ikra dwóch wątków podrzędnych.Pierwszy wątku, wątek A, włącza ustawienia regionalne na wątek poprzez wywołanie _configthreadlocale(_ENABLE_PER_THREAD_LOCALE).Drugi wątek, B wątku, a także głównego wątku, nie należy włączać ustawień regionalnych na wątek.Wątek B, a następnie przechodzi do zmiany ustawień regionalnych, przy użyciu locale::global metoda standardowa biblioteka języka C++.

Od wątku B nie ma włączone ustawienia regionalne na wątek, funkcje C Runtime Library w wątku B i w głównym wątku uruchomiony przy użyciu locale "francuskie".Funkcje C Runtime Library w wątku A Kontynuuj, aby użyć ustawień regionalnych "C", ponieważ wątek A ma włączone ustawienia regionalne na wątek.Jednakże, ponieważ locale::global metoda zmienia ustawienia regionalne "globalny", wszystkie obiekty standardowa biblioteka języka C++ w wszystkie wątki rozpocząć korzystanie z narzędzia locale "francuskie".

// 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;
}
  

Zobacz też

Informacje

_beginthread, _beginthreadex

_configthreadlocale

setlocale

Internacjonalizacja

Regionalne

<clocale>

<locale>

locale — Klasa

Koncepcje

Obsługa wielowątkowości w przypadku starszego kodu (Visual C++)