Aracılığıyla paylaş


Çoklu İş Parçacığı Kullanımı ve Yerel Ayarlar

C Çalışma Zamanı Kitaplığı ve Standart C++ Kitaplığı, programınızın yerel ayarları değiştirmek için destek sağlar. Bu konu çok iş parçacıklı bir uygulamada her iki kitaplığın da yerel ayar işlevselliğini kullanırken çıkabilecek sorunları açıklamaktadır.

Açıklamalar

C Çalışma Zamanı Kitaplığı ile _beginthread ve _beginthreadex işlevlerini kullanan birden çok iş parçacıklı uygulamalar oluşturabilirsiniz. Bu konu yalnızca bu işlevleri kullanılarak oluşturulan çok iş parçacıklı uygulamalarını kapsamaktadır. Daha fazla bilgi için bkz. _beginthread, _beginthreadex.

C Çalışma Zamanı kitaplığını kullanarak yerel ayarları değiştirmek için setlocale işlevini kullanın. Visual C++ öğesinin önceki sürümlerinde, bu işlev her zaman tüm uygulama boyunca yereli değiştirir. İş parçacığı başına temel üzerinde yerel ayarları ayarlamaya ilişkin bir destek artık mevcut. Bu, _configthreadlocale işlevi kullanılarak yapılır. setlocale öğesinin geçerli iş parçacığında sadece yerel ayarı değiştirmesi gerektiğini belirtmek için o iş parçacığındaki _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) öğesini çağırın. Diğer yandan, _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) çağırmak bu iş parçasının genel yerel ayarı kullanmasına neden olur ve iş parçasına herhangi bir setlocale çağrısı iş parçasının yerel ayarı tarafından açık bir şekilde etkinleştirilmemiş, tüm iş parçalarında yerel ayarı değiştirir.

C++ Çalışma Zamanı kitaplığını kullanarak yerel ayarları değiştirmek için locale Class işlevini kullanın. locale::global yöntemini çağırarak, İş parçacığı yerel ayarı başına açıkça etkinleştirilmemiş her iş parçacığındaki yerel ayarı değiştirebilirsiniz. Tek iş parçacığı veya uygulamanın bir bölümündeki yerel ayarları değiştirmek için sadece locale nesnesinin o iş parçacığı veya kod parçasında bir örneğini oluşturun.

Not

locale::global öğesini çağırmak, hem Standart C++ Kitaplığı hem de C Çalışma Zamanı Kitaplığı için yerel ayarı değiştirir. Ancak, setlocale aramak yalnızca C Çalışma Zamanı Kitaplığı yerel ayarını değiştirir; Standart C++ Kitaplığı etkilenmez.

Aşağıdaki örnekler birçok farklı senaryoda bir uygulamanın yerel ayarını değiştirmek için setlocale, locale Class ve _configthreadlocale işlevlerinin nasıl kullanıldığını gösterir.

Örnek

Bu örnekte ana iş parçacığı iki alt iş parçacığı olarak çoğaltılır. İlk iş parçacığı İş Parçacığı A, _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) çağırarak iş parçacığı başına yereli etkinleştirir. İkinci iş parçacığı, İş Parçacığı B yanı sıra ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. Bu durumda A iş parçacığı, C Çalışma Zamanı Kitaplığı'nın setlocale işlevini kullanarak yerel ayarı değiştirmeye geçer.

İş Parçacığı A öğesinde iş parçacığı başına yerel ayar etkin olduğundan, İş Parçacığı A içinde yalnızca C Çalışma Zamanı Kitaplığı işlevleri "Fransızca" yerel ayarını kullanmaya başlar. B İş Parçacığı'ndaki ve ana iş parçacığındaki C Çalışma Zamanı Kitaplığı işlevleri "C" yerel ayarını kullanmaya devam eder. Ayrıca, setlocale, Standart C++ Kitaplığı yerel ayarını etkilemediğinden tüm Standart C++ Kitaplığı nesneleri "C" yerel ayarını kullanmaya devam eder.

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

Bu örnekte ana iş parçacığı iki alt iş parçacığı olarak çoğaltılır. İlk iş parçacığı İş Parçacığı A, _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) çağırarak iş parçacığı başına yereli etkinleştirir. İkinci iş parçacığı, İş Parçacığı B yanı sıra ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. Bu durumda A iş parçacığı, Standart C++ Kitaplığı'nın locale::global yöntemini kullanarak yerel ayarı değiştirmeye geçer.

İş Parçacığı A öğesinde iş parçacığı başına yerel ayar etkin olduğundan, İş Parçacığı A içinde yalnızca C Çalışma Zamanı Kitaplığı işlevleri "Fransızca" yerel ayarını kullanmaya başlar. B İş Parçacığı'ndaki ve ana iş parçacığındaki C Çalışma Zamanı Kitaplığı işlevleri "C" yerel ayarını kullanmaya devam eder. Ancak, locale::global yöntemi değişiklikleri yerel ayarları "genel" olarak değiştirdiğinden, bütün iş parçacıklarındaki tüm standart C++ Kitaplığı nesneleri "Fransız" yerel ayarlarını kullanmaya başlar.

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

Bu örnekte ana iş parçacığı iki alt iş parçacığı olarak çoğaltılır. İlk iş parçacığı İş Parçacığı A, _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) çağırarak iş parçacığı başına yereli etkinleştirir. İkinci iş parçacığı, İş Parçacığı B yanı sıra ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. Bu durumda B iş parçacığı, C Çalışma Zamanı Kitaplığı'nın setlocale işlevini kullanarak yerel ayarı değiştirmeye geçer.

İş Parçacığı B öğesinde iş parçacığı başına yerel ayar etkin olmadığından, İş Parçacığı B içindeki ve ana iş parçacığındaki C Çalışma Zamanı Kitaplığı işlevleri "Fransızca" yerel ayarını kullanmaya başlar. A İş Parçacığı öğesindeki C Çalışma Zamanı Kitaplığı işlevleri "C" yerel ayarını kullanmaya devam eder, çünkü A İş Parçacığı'nın iş parçacığı başına etkinleştirilmiş bir yerel ayarı vardır. Ayrıca, setlocale, Standart C++ Kitaplığı yerel ayarını etkilemediğinden tüm Standart C++ Kitaplığı nesneleri "C" yerel ayarını kullanmaya devam eder.

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

Bu örnekte ana iş parçacığı iki alt iş parçacığı olarak çoğaltılır. İlk iş parçacığı İş Parçacığı A, _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) çağırarak iş parçacığı başına yereli etkinleştirir. İkinci iş parçacığı, İş Parçacığı B yanı sıra ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. Bu durumda B iş parçacığı, Standart C++ Kitaplığı'nın locale::global yöntemini kullanarak yereli değiştirmeye geçer.

İş Parçacığı B öğesinde iş parçacığı başına yerel ayar etkin olmadığından, İş Parçacığı B içindeki ve ana iş parçacığındaki C Çalışma Zamanı Kitaplığı işlevleri "Fransızca" yerel ayarını kullanmaya başlar. A İş Parçacığı öğesindeki C Çalışma Zamanı Kitaplığı işlevleri "C" yerel ayarını kullanmaya devam eder, çünkü A İş Parçacığı'nın iş parçacığı başına etkinleştirilmiş bir yerel ayarı vardır. Ancak, locale::global yöntemi değişiklikleri yerel ayarları "genel" olarak değiştirdiğinden, bütün iş parçacıklarındaki tüm standart C++ Kitaplığı nesneleri "Fransız" yerel ayarlarını kullanmaya başlar.

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

Ayrıca bkz.

Başvuru

_beginthread, _beginthreadex

_configthreadlocale

setlocale

Internationalization

Locale

<clocale>

<locale>

locale Class

Kavramlar

Çoklu İş Parçacığı Kullanımı