Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La bibliothèque d’exécution C et la bibliothèque standard C++ prennent toutes deux en charge la modification des paramètres régionaux de votre programme. Cette rubrique traite des problèmes qui surviennent lors de l’utilisation de la fonctionnalité de paramètres régionaux des deux bibliothèques dans une application multithread.
Remarques
Avec la bibliothèque d’exécution C, vous pouvez créer des applications multithread à l’aide des fonctions _beginthread et _beginthreadex. Cette rubrique traite uniquement des applications multithread créées à l’aide de ces fonctions. Pour plus d’informations, consultez _beginthread, _beginthreadex.
Pour modifier les paramètres régionaux à l’aide de la bibliothèque d’exécution C, utilisez la fonction setlocale. Dans les versions précédentes de Visual C++, cette fonction modifiait toujours les paramètres régionaux dans toute l’application. Il est désormais possible de définir les paramètres régionaux pour chaque thread. Pour ce faire, utilisez la fonction _configthreadlocale. Pour spécifier que setlocale ne doit modifier la locale que dans le thread en cours, appelez _configthreadlocale(_ENABLE_PER_THREAD_LOCALE) dans ce thread. À l’inverse, l’appel de _configthreadlocale(_DISABLE_PER_THREAD_LOCALE) entraînera l’utilisation de la locale globale par ce thread, et tout appel à setlocale dans ce thread modifiera la locale dans tous les threads qui n’ont pas explicitement activé la locale par thread.
Pour modifier la locale à l’aide de la bibliothèque d’exécution C++, utilisez la classe locale. En appelant la méthode locale::global, vous modifiez la locale dans tous les threads qui n’ont pas explicitement activé la locale par thread. Pour modifier la locale dans un seul thread ou une partie d’une application, créez simplement une instance d’un objet locale dans ce thread ou cette partie du code.
Note
L’appel de locale::global modifie la locale à la fois pour la bibliothèque standard C++ et la bibliothèque d’exécution C. Cependant, l’appel de setlocale modifie uniquement la locale pour la bibliothèque d’exécution C ; la bibliothèque standard C++ n’est pas affectée.
Les exemples suivants montrent comment utiliser la fonction setlocale, la classe locale et la fonction _configthreadlocale pour modifier la locale d’une application dans plusieurs scénarios différents.
Exemple : modification de la locale avec la locale par thread activée
Dans cet exemple, le thread principal génère deux threads enfants. Le premier thread, Thread A, active la locale par thread en appelant _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Le deuxième thread, Thread B, ainsi que le thread principal, n’activent pas la locale par thread. Le thread A procède ensuite à la modification de la locale à l’aide de la fonction setlocale de la bibliothèque d’exécution C.
Comme le thread A a activé la locale par thread, seules les fonctions de la bibliothèque d’exécution C dans le thread A commencent à utiliser la locale « french ». Les fonctions de la bibliothèque d’exécution C dans le thread B et dans le thread principal continuent d’utiliser la locale « C ». De plus, comme setlocale n’affecte pas la locale de la bibliothèque standard C++, tous les objets de la bibliothèque standard C++ continuent d’utiliser la locale « 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"
Exemple : modification de la locale globale avec la locale par thread activée
Dans cet exemple, le thread principal génère deux threads enfants. Le premier thread, Thread A, active la locale par thread en appelant _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Le deuxième thread, Thread B, ainsi que le thread principal, n’activent pas la locale par thread. Le thread A procède ensuite à la modification de la locale à l’aide de la méthode locale::global de la bibliothèque standard C++.
Comme le thread A a activé la locale par thread, seules les fonctions de la bibliothèque d’exécution C dans le thread A commencent à utiliser la locale « french ». Les fonctions de la bibliothèque d’exécution C dans le thread B et dans le thread principal continuent d’utiliser la locale « C ». Cependant, comme la méthode locale::global modifie la locale « globalement », tous les objets de la bibliothèque standard C++ dans tous les threads commencent à utiliser la locale « française ».
// 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"
Exemple : modification de la locale sans activation de la locale par thread
Dans cet exemple, le thread principal génère deux threads enfants. Le premier thread, Thread A, active la locale par thread en appelant _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Le deuxième thread, Thread B, ainsi que le thread principal, n’activent pas la locale par thread. Le thread B procède ensuite à la modification de la locale à l’aide de la fonction setlocale de la bibliothèque d’exécution C.
Étant donné que le thread B n’a pas activé la locale par thread, les fonctions de la bibliothèque d’exécution C dans le thread B et dans le thread principal commencent à utiliser la locale « french ». Les fonctions de la bibliothèque d’exécution C dans le thread A continuent d’utiliser la locale « C » car le thread A a activé la locale par thread. De plus, comme setlocale n’affecte pas la locale de la bibliothèque standard C++, tous les objets de la bibliothèque standard C++ continuent d’utiliser la locale « 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"
Exemple : modification de la locale globale sans activation de la locale par thread
Dans cet exemple, le thread principal génère deux threads enfants. Le premier thread, Thread A, active la locale par thread en appelant _configthreadlocale(_ENABLE_PER_THREAD_LOCALE). Le deuxième thread, Thread B, ainsi que le thread principal, n’activent pas la locale par thread. Le thread B procède ensuite à la modification de la locale à l’aide de la méthode locale::global de la bibliothèque standard C++.
Étant donné que le thread B n’a pas activé la locale par thread, les fonctions de la bibliothèque d’exécution C dans le thread B et dans le thread principal commencent à utiliser la locale « french ». Les fonctions de la bibliothèque d’exécution C dans le thread A continuent d’utiliser la locale « C » car le thread A a activé la locale par thread. Cependant, comme la méthode locale::global modifie la locale « globalement », tous les objets de la bibliothèque standard C++ dans tous les threads commencent à utiliser la locale « française ».
// 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"
Voir aussi
Prise en charge du multithreading pour les anciens codes (Visual C++)
_beginthread, _beginthreadex
_configthreadlocale
setlocale
Internationalisation
Locale
<clocale>
<locale>
Classe locale