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"

Consulte também

Conceitos

Multiencadeamento

Referência

_beginthread, _beginthreadex

_configthreadlocale

setLocale

Internacionalização

Localidade

< clocale >

< localidade >

localidade Classe