Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Bounce.c to przykładowy program wielowątkowy, który tworzy nowy wątek za każdym razem, gdy litera a
lub A
jest wpisywana. Każdy wątek odbija literę innego koloru wokół ekranu. Można utworzyć maksymalnie 32 wątki. Normalne zakończenie programu występuje, gdy q
lub Q
jest typizowane.
Kompilowanie i łączenie programu wielowątkowego
Programy są domyślnie kompilowane jako wielowątkowe.
Aby skompilować i połączyć program wielowątkowy Bounce.c z poziomu środowiska deweloperskiego
W menu Plik wybierz pozycję Nowy>projekt.
W oknie dialogowym Tworzenie nowego projektu wybierz szablon Aplikacja konsolowa z tagami C++, Windows i Console. Wybierz przycisk Dalej , aby kontynuować.
W oknie dialogowym Konfigurowanie nowego projektu wprowadź nazwę projektu, na przykład "Bounce". Wybierz pozycję Utwórz , aby kontynuować.
W oknie Eksplorator rozwiązań otwórz folder Pliki źródłowe w projekcie i zmień nazwę pliku źródłowego na rozszerzenie c.
W oknie edycji usuń istniejący kod źródłowy i zastąp go przykładowym kodem.
W menu Kompilacja wybierz pozycję Kompiluj rozwiązanie.
Naciśnij F5 , aby uruchomić program w debugerze.
W menu Plik wybierz pozycję Nowy>projekt.
W oknie dialogowym Nowy projekt wybierz pozycję Visual C++ w okienku po lewej stronie, a następnie wybierz pozycję Pusty projekt w środkowym okienku.
W polu Edytowanie nazwy wprowadź nazwę projektu, na przykład "Bounce". Wybierz przycisk OK , aby utworzyć pusty projekt.
W oknie Eksplorator rozwiązań otwórz folder Pliki źródłowe w projekcie i dodaj plik zawierający kod źródłowy języka C do projektu.
W menu Kompilacja skompiluj projekt, wybierając polecenie Kompiluj rozwiązanie .
Naciśnij F5 , aby uruchomić program w debugerze.
Naciśnij a, aby utworzyć nowy wątek. Każdy wątek odbija znak innego koloru wokół ekranu.
Naciśnij q , aby zakończyć pracę.
Aby skompilować i połączyć program wielowątkowy Bounce.c z wiersza polecenia
Otwórz wiersz polecenia narzędzi programu Visual Studio. Dzięki temu ścieżka zostanie ustawiona tak, aby zawierała kompilator.
Skompiluj i połącz program:
cl bounce.c
Przykład
Aby skompilować się w wierszu polecenia, skopiuj i zapisz ten przykład w pliku źródłowym z rozszerzeniem c. W środowisku IDE zastąp dowolny kod źródłowy utworzony przez szablon następującym przykładem:
// sample_multithread_c_program.c
// compile with: /c
//
// Bounce - Creates a new thread each time the letter 'a' is typed.
// Each thread bounces a character of a different color around
// the screen. All threads are terminated when the letter 'Q' is
// entered.
//
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
#define MAX_THREADS 32
// The function getrandom returns a random number between
// min and max, which must be in integer range.
#define getrandom( min, max ) (SHORT)((rand() % (int)(((max) + 1) - \
(min))) + (min))
int main(void); // Thread 1: main
void KbdFunc(void); // Keyboard input, thread dispatch
void BounceProc(void* pMyID); // Threads 2 to n: display
void ClearScreen(void); // Screen clear
void ShutDown(void); // Program shutdown
void WriteTitle(int ThreadNum); // Display title bar information
HANDLE hConsoleOut; // Handle to the console
HANDLE hRunMutex; // "Keep Running" mutex
HANDLE hScreenMutex; // "Screen update" mutex
int ThreadNr = 0; // Number of threads started
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; // Console information
COORD consoleSize;
BOOL bTrails = FALSE;
HANDLE hThreads[MAX_THREADS] = { NULL }; // Handles for created threads
int main(void) // Thread One
{
// Get display screen information & clear the screen.
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut, &csbiInfo);
consoleSize.X = csbiInfo.srWindow.Right;
consoleSize.Y = csbiInfo.srWindow.Bottom;
ClearScreen();
WriteTitle(0);
// Create the mutexes and reset thread count.
hScreenMutex = CreateMutexW(NULL, FALSE, NULL); // Cleared
hRunMutex = CreateMutexW(NULL, TRUE, NULL); // Set
// Start waiting for keyboard input to dispatch threads or exit.
KbdFunc();
// All threads done. Clean up handles.
if (hScreenMutex) CloseHandle(hScreenMutex);
if (hRunMutex) CloseHandle(hRunMutex);
if (hConsoleOut) CloseHandle(hConsoleOut);
}
void ShutDown(void) // Shut down threads
{
// Tell all threads to die
ReleaseMutex(hRunMutex);
while (ThreadNr > 0)
{
// Wait for each thread to complete
WaitForSingleObject(hThreads[--ThreadNr], INFINITE);
}
// Clean up display when done
WaitForSingleObject(hScreenMutex, INFINITE);
ClearScreen();
}
void KbdFunc(void) // Dispatch and count threads.
{
int KeyInfo;
do
{
KeyInfo = _getch();
if (tolower(KeyInfo) == 'a' &&
ThreadNr < MAX_THREADS)
{
++ThreadNr;
hThreads[ThreadNr] =
(HANDLE)_beginthread(BounceProc, 0, (void*)(uintptr_t)ThreadNr);
WriteTitle(ThreadNr);
}
if (tolower(KeyInfo) == 't')
{
bTrails = !bTrails;
}
} while (tolower(KeyInfo) != 'q');
ShutDown();
}
void BounceProc(void* pMyID)
{
wchar_t MyCell, OldCell;
WORD MyAttrib, OldAttrib = 0;
wchar_t BlankCell = 0x20;
COORD Coords, Delta;
COORD Old = { 0,0 };
DWORD Dummy;
int MyID = (int)(uintptr_t)pMyID;
// Generate update increments and initial
// display coordinates.
srand(MyID * 3);
Coords.X = getrandom(0, consoleSize.X - 1);
Coords.Y = getrandom(0, consoleSize.Y - 1);
Delta.X = getrandom(-3, 3);
Delta.Y = getrandom(-3, 3);
// Set up character & generate color
// attribute from thread number.
if (MyID > 16)
MyCell = (wchar_t)(0x60 + MyID - 16); // lower case
else
MyCell = (wchar_t)(0x40 + MyID); // upper case
MyAttrib = MyID & 0x0f; // force black background
do
{
// Wait for display to be available, then lock it.
WaitForSingleObject(hScreenMutex, INFINITE);
if (!bTrails)
{
// If we still occupy the old screen position, blank it out.
ReadConsoleOutputCharacterW(hConsoleOut, &OldCell, 1,
Old, &Dummy);
ReadConsoleOutputAttribute(hConsoleOut, &OldAttrib, 1,
Old, &Dummy);
if ((OldCell == MyCell) && (OldAttrib == MyAttrib))
WriteConsoleOutputCharacterW(hConsoleOut, &BlankCell, 1,
Old, &Dummy);
}
// Draw new character, then clear screen lock
WriteConsoleOutputCharacterW(hConsoleOut, &MyCell, 1,
Coords, &Dummy);
WriteConsoleOutputAttribute(hConsoleOut, &MyAttrib, 1,
Coords, &Dummy);
ReleaseMutex(hScreenMutex);
// Increment the coordinates for next placement of the block.
Old.X = Coords.X;
Old.Y = Coords.Y;
Coords.X += Delta.X;
Coords.Y += Delta.Y;
// If we are about to go off the screen, reverse direction
if (Coords.X < 0 || Coords.X >= consoleSize.X)
{
Delta.X = -Delta.X;
Beep(400, 50);
}
if (Coords.Y < 0 || Coords.Y > consoleSize.Y)
{
Delta.Y = -Delta.Y;
Beep(600, 50);
}
}
// Repeat while RunMutex is still taken.
while (WaitForSingleObject(hRunMutex, 75L) == WAIT_TIMEOUT);
}
void WriteTitle(int ThreadNum)
{
enum
{
sizeOfNThreadMsg = 120
};
wchar_t NThreadMsg[sizeOfNThreadMsg] = { L"" };
swprintf_s(NThreadMsg, sizeOfNThreadMsg,
L"Threads running: %02d. Press 'A' "
L"to start a thread, 'T' to toggle "
L"trails, 'Q' to quit.", ThreadNum);
SetConsoleTitleW(NThreadMsg);
}
void ClearScreen(void)
{
DWORD dummy = 0;
COORD Home = { 0, 0 };
FillConsoleOutputCharacterW(hConsoleOut, L' ',
consoleSize.X * consoleSize.Y,
Home, &dummy);
}