Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Creating Threads.doc
Скачиваний:
4
Добавлен:
10.11.2019
Размер:
144.9 Кб
Скачать

Requirements

Routine

Required header

Compatibility

_beginthread

<process.h>

Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition, Windows Millennium Edition, Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003

_beginthreadex

<process.h>

Windows 95, Windows 98, Windows 98 Second Edition, Windows Millennium Edition, Windows Millennium Edition, Windows NT 4.0, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003

For more compatibility information, see Compatibility in the Introduction.

Libraries

Multithreaded versions of the C run-time libraries only.

To use _beginthread or _beginthreadex, the application must link with one of the multithreaded C run-time libraries.

Example

The following example uses _beginthread and _endthread.

 

Copy Code

// crt_BEGTHRD.C

// compile with: /MT /D "_X86_" /c

// processor: x86

#include <windows.h>

#include <process.h> /* _beginthread, _endthread */

#include <stddef.h>

#include <stdlib.h>

#include <conio.h>

void Bounce( void *ch );

void CheckKey( void *dummy );

/* GetRandom returns a random integer between min and max. */

#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

BOOL repeat = TRUE; /* Global repeat flag and video variable */

HANDLE hStdOut; /* Handle for console window */

CONSOLE_SCREEN_BUFFER_INFO csbi; /* Console information structure */

int main()

{

CHAR ch = 'A';

hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );

/* Get display screen's text row and column information. */

GetConsoleScreenBufferInfo( hStdOut, &csbi );

/* Launch CheckKey thread to check for terminating keystroke. */

_beginthread( CheckKey, 0, NULL );

/* Loop until CheckKey terminates program. */

while( repeat )

{

/* On first loops, launch character threads. */

_beginthread( Bounce, 0, (void *) (ch++) );

/* Wait one second between loops. */

Sleep( 1000L );

}

}

/* CheckKey - Thread to wait for a keystroke, then clear repeat flag. */

void CheckKey( void *dummy )

{

_getch();

repeat = 0; /* _endthread implied */

}

/* Bounce - Thread to create and and control a colored letter that moves

* around on the screen.

*

* Params: ch - the letter to be moved

*/

void Bounce( void *ch )

{

/* Generate letter and color attribute from thread argument. */

char blankcell = 0x20;

char blockcell = (char) ch;

BOOL first = TRUE;

COORD oldcoord, newcoord;

DWORD result;

/* Seed random number generator and get initial location. */

srand( _threadid );

newcoord.X = GetRandom( 0, csbi.dwSize.X - 1 );

newcoord.Y = GetRandom( 0, csbi.dwSize.Y - 1 );

while( repeat )

{

/* Pause between loops. */

Sleep( 100L );

/* Blank out our old position on the screen, and draw new letter. */

if( first )

first = FALSE;

else

WriteConsoleOutputCharacter( hStdOut, &blankcell, 1, oldcoord, &result );

WriteConsoleOutputCharacter( hStdOut, &blockcell, 1, newcoord, &result );

/* Increment the coordinate for next placement of the block. */

oldcoord.X = newcoord.X;

oldcoord.Y = newcoord.Y;

newcoord.X += GetRandom( -1, 1 );

newcoord.Y += GetRandom( -1, 1 );

/* Correct placement (and beep) if about to go off the screen. */

if( newcoord.X < 0 )

newcoord.X = 1;

else if( newcoord.X == csbi.dwSize.X )

newcoord.X = csbi.dwSize.X - 2;

else if( newcoord.Y < 0 )

newcoord.Y = 1;

else if( newcoord.Y == csbi.dwSize.Y )

newcoord.Y = csbi.dwSize.Y - 2;

/* If not at a screen border, continue, otherwise beep. */

else

continue;

Beep( ((char) ch - 'A') * 100, 175 );

}

/* _endthread given to terminate */

_endthread();

}

Input

 

press any key to end

The following sample code demonstrates how you can use the thread handle returned by _beginthreadex with the synchronization API WaitForSingleObject. The main thread waits for the second thread to terminate before it continues. When the second thread calls _endthreadex, it causes its thread object to go to the signaled state. This allows the primary thread to continue running. This cannot be done with _beginthread and _endthread, because _endthread calls CloseHandle, destroying the thread object before it can be set to the signaled state.

 

Copy Code

// crt_begthrdex.cpp

// compile with: /MT

#include <windows.h>

#include <stdio.h>

#include <process.h>

unsigned Counter;

unsigned __stdcall SecondThreadFunc( void* pArguments )

{

printf( "In second thread...\n" );

while ( Counter < 1000000 )

Counter++;

_endthreadex( 0 );

return 0;

}

int main()

{

HANDLE hThread;

unsigned threadID;

printf( "Creating second thread...\n" );

// Create the second thread.

hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );

// Wait until second thread terminates. If you comment out the line

// below, Counter will not be correct because the thread has not

// terminated, and Counter most likely has not been incremented to

// 1000000 yet.

WaitForSingleObject( hThread, INFINITE );

printf( "Counter should be 1000000; it is-> %d\n", Counter );

// Destroy the thread object.

CloseHandle( hThread );

}

Output

 

Creating second thread...

In second thread...

Counter should be 1000000; it is-> 1000000

.NET Framework Equivalent

System::Threading::Thread::Start

See Also

Reference

Process and Environment Control _endthread, _endthreadex abort exit, _exit GetExitCodeThread

Using Mutex Objects

You can use a mutex object to protect a shared resource from simultaneous access by multiple threads or processes. Each thread must wait for ownership of the mutex before it can execute the code that accesses the shared resource. For example, if several threads share access to a database, the threads can use a mutex object to permit only one thread at a time to write to the database.

In the following example, a process uses the CreateMutex function to create a mutex object.

HANDLE hMutex;

// Create a mutex with no initial owner.

hMutex = CreateMutex(

NULL, // default security attributes

FALSE, // initially not owned

NULL); // unnamed mutex

if (hMutex == NULL)

{

printf("CreateMutex error: %d\n", GetLastError());

}

When a thread of this process writes to the database, as in the next example, it first requests ownership of the mutex. If it gets ownership, the thread writes to the database and then releases its ownership.

The example uses structured exception-handling syntax to ensure that the thread properly releases the mutex object. The __finally block of code is executed no matter how the __try block terminates (unless the __try block includes a call to the TerminateThread function). This prevents the mutex object from being abandoned inadvertently.

BOOL FunctionToWriteToDatabase(HANDLE hMutex)

{

DWORD dwWaitResult;

// Request ownership of mutex.

dwWaitResult = WaitForSingleObject(

hMutex, // handle to mutex

5000L); // five-second time-out interval

switch (dwWaitResult)

{

// The thread got mutex ownership.

case WAIT_OBJECT_0:

__try {

// Write to the database.

}

__finally {

// Release ownership of the mutex object.

if (! ReleaseMutex(hMutex))

{

// Deal with error.

}

break;

}

// Cannot get mutex ownership due to time-out.

case WAIT_TIMEOUT:

return FALSE;

// Got ownership of the abandoned mutex object.

case WAIT_ABANDONED:

return FALSE;

}

return TRUE;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]