Aracılığıyla paylaş


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

Hem C Çalışma Zamanı Kitaplığı hem de C++ Standart Kitaplığı, programınızın yerel ayarını değiştirmek için destek sağlar. Bu konuda, çok iş parçacıklı bir uygulamada her iki kitaplığın yerel ayar işlevselliği kullanılırken ortaya çıkan sorunlar ele alınmaktadır.

Açıklamalar

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

C Çalışma Zamanı Kitaplığı'nı kullanarak yerel ayarı değiştirmek için setlocale işlevini kullanın. Visual C++'ın önceki sürümlerinde bu işlev her zaman uygulamanın tamamında yerel ayarı değiştirirdi. Artık iş parçacığı başına yerel ayarın ayarlanması destekleniyor. Bu işlem _configthreadlocale işlevi kullanılarak yapılır. Setlocale öğesinin yalnızca geçerli iş parçacığındaki yerel ayarı değiştirmesi gerektiğini belirtmek için bu iş parçacığında çağrısında _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) bulunabilirsiniz. Buna karşılık, çağrı _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) bu iş parçacığının genel yerel ayarı kullanmasına neden olur ve bu iş parçacığındaki setlocale çağrısı, iş parçacığı başına yerel ayarı açıkça etkinleştirmemiş tüm iş parçacıklarında yerel ayarı değiştirir.

C++ Çalışma Zamanı Kitaplığı'nı kullanarak yerel ayarı değiştirmek için yerel ayar Sınıfı'nı kullanın. locale::global yöntemini çağırarak, iş parçacığı başına yerel ayarı açıkça etkinleştirmemiş her iş parçacığında yerel ayarı değiştirirsiniz. Uygulamanın tek bir iş parçacığında veya bir bölümünde yerel ayarı değiştirmek için, bu iş parçacığında veya kodun bir bölümünde nesnenin locale bir örneğini oluşturmanız yeterlidir.

Dekont

Locale::global çağrısı, hem C++ Standart Kitaplığı hem de C Çalışma Zamanı Kitaplığı için yerel ayarı değiştirir. Ancak, setlocale çağrısı yalnızca C Çalışma Zamanı Kitaplığı'nın yerel ayarını değiştirir; C++ Standart Kitaplığı etkilenmez.

Aşağıdaki örneklerde setlocale işlevinin, yerel ayarın ve _configthreadlocale işlevinin bir uygulamanın yerel ayarını birkaç farklı senaryoda değiştirmek için nasıl kullanılacağı gösterilmektedir.

Örnek: İş parçacığı başına yerel ayar etkinken yerel ayarı değiştirme

Bu örnekte, ana iş parçacığı iki alt iş parçacığı oluşturur. İlk iş parçacığı olan İş Parçacığı A, çağrısı _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)yaparak iş parçacığı başına yerel ayarı etkinleştirir. İkinci iş parçacığı olan İş Parçacığı B ve ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. Ardından İş Parçacığı A, C Çalışma Zamanı Kitaplığı'nın setlocale işlevini kullanarak yerel ayarı değiştirmeye devam eder.

İş Parçacığı A'da iş parçacığı başına yerel ayar etkinleştirildiğinden, yalnızca İş Parçacığı A'daki 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 C++ Standart Kitaplığı yerel ayarını etkilemediğinden, tüm C++ Standart 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;
}
[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"

Örnek: İş parçacığı başına yerel ayar etkinken genel yerel ayarı değiştirme

Bu örnekte, ana iş parçacığı iki alt iş parçacığı oluşturur. İlk iş parçacığı olan İş Parçacığı A, çağrısı _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)yaparak iş parçacığı başına yerel ayarı etkinleştirir. İkinci iş parçacığı olan İş Parçacığı B ve ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. A İş Parçacığı daha sonra C++ Standart Kitaplığı'nın locale::global yöntemini kullanarak yerel ayarı değiştirmeye devam eder.

İş Parçacığı A'da iş parçacığı başına yerel ayar etkinleştirildiğinden, yalnızca İş Parçacığı A'daki 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 yerel ayarı "genel" olarak değiştirdiğinden, tüm iş parçacıklarındaki tüm C++ Standart Kitaplığı nesneleri "fransızca" yerel ayarı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;
}
[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"

Örnek: İş parçacığı başına yerel ayar etkinleştirilmeden yerel ayarı değiştirme

Bu örnekte, ana iş parçacığı iki alt iş parçacığı oluşturur. İlk iş parçacığı olan İş Parçacığı A, çağrısı _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)yaparak iş parçacığı başına yerel ayarı etkinleştirir. İkinci iş parçacığı olan İş Parçacığı B ve ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. Ardından İş Parçacığı B, C Çalışma Zamanı Kitaplığı'nın setlocale işlevini kullanarak yerel ayarı değiştirmeye devam eder.

İş Parçacığı B'de iş parçacığı başına yerel ayar etkinleştirilmediğinden, B İş Parçacığındaki ve ana iş parçacığındaki C Çalışma Zamanı Kitaplığı işlevleri "fransızca" yerel ayarını kullanmaya başlar. İş Parçacığı A'daki C Çalışma Zamanı Kitaplığı işlevleri, İş Parçacığı A'da iş parçacığı başına yerel ayar etkinleştirildiğinden "C" yerel ayarını kullanmaya devam eder. Ayrıca, setlocale C++ Standart Kitaplığı yerel ayarını etkilemediğinden, tüm C++ Standart 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;
}
[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"

Örnek: İş parçacığı başına yerel ayar etkinleştirilmeden genel yerel ayarı değiştirme

Bu örnekte, ana iş parçacığı iki alt iş parçacığı oluşturur. İlk iş parçacığı olan İş Parçacığı A, çağrısı _configthreadlocale(_ENABLE_PER_THREAD_LOCALE)yaparak iş parçacığı başına yerel ayarı etkinleştirir. İkinci iş parçacığı olan İş Parçacığı B ve ana iş parçacığı, iş parçacığı başına yerel ayarı etkinleştirmez. B iş parçacığı daha sonra C++ Standart Kitaplığı'nın locale::global yöntemini kullanarak yerel ayarı değiştirmeye devam eder.

İş Parçacığı B'de iş parçacığı başına yerel ayar etkinleştirilmediğinden, B İş Parçacığındaki ve ana iş parçacığındaki C Çalışma Zamanı Kitaplığı işlevleri "fransızca" yerel ayarını kullanmaya başlar. İş Parçacığı A'daki C Çalışma Zamanı Kitaplığı işlevleri, İş Parçacığı A'da iş parçacığı başına yerel ayar etkinleştirildiğinden "C" yerel ayarını kullanmaya devam eder. Ancak locale::global yöntemi yerel ayarı "genel" olarak değiştirdiğinden, tüm iş parçacıklarındaki tüm C++ Standart Kitaplığı nesneleri "fransızca" yerel ayarı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;
}
[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"

Ayrıca bkz.

Eski Kod için Çoklu İş Parçacığı Kullanma Desteği (Visual C++)
_beginthread, _beginthreadex
_configthreadlocale
setlocale
Uluslararası duruma getirme
Yerel ayar
<klokale>
<yerel ayar>
locale Sınıfı