那我找到是這個,就參考底下的範例去分析吧!
依依瞭解C在執行緒的方式以及解決方法,如果你有讀完OS聖經,想必更好懂原因。
哈哈,等你會了老闆一定會愛死你的 哈哈
對了,如果不懂的話下面有我找到的參考資料,慢慢看吧
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
#define MAX_THREADS 32
#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 * MyID ); // 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; // Number of threads started
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; // Console information
int main() // Thread One
{
// Get display screen information & clear the screen.
hConsoleOut = GetStdHandle( STD_OUTPUT_HANDLE );//取得使用者輸入的字元
GetConsoleScreenBufferInfo( hConsoleOut, &csbiInfo ); //取得終端機的介面資訊
ClearScreen(); //清除螢幕
WriteTitle( 0 ); //寫入標題
// Create the mutexes and reset thread count.
hScreenMutex = CreateMutex( NULL, FALSE, NULL ); // 清除執行緒同步
hRunMutex = CreateMutex( NULL, TRUE, NULL ); // 設定所有執行緒同步
ThreadNr = 0;
// Start waiting for keyboard input to dispatch threads or exit.
KbdFunc();
// All threads done. Clean up handles.
CloseHandle( hScreenMutex ); //釋放資源
CloseHandle( hRunMutex );
CloseHandle( hConsoleOut );
}
void ShutDown( void ) // Shut down threads
{
while ( ThreadNr > 0 )
{
// Tell thread to die and record its death.
ReleaseMutex( hRunMutex ); //釋放執行緒
ThreadNr--;
}
// 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++;
_beginthread( BounceProc, 0, &ThreadNr ); //啟動執行緒
WriteTitle( ThreadNr ); //
}
} while( tolower( KeyInfo ) != 'q' );
ShutDown();
}
void BounceProc( void *pMyID )
{
char MyCell, OldCell;
WORD MyAttrib, OldAttrib;
char BlankCell = 0x20;
COORD Coords, Delta;
COORD Old = {0,0};
DWORD Dummy;
char *MyID = (char*)pMyID;
// Generate update increments and initial
// display coordinates.
srand( (unsigned int) *MyID * 3 );
Coords.X = getrandom( 0, csbiInfo.dwSize.X - 1 );
Coords.Y = getrandom( 0, csbiInfo.dwSize.Y - 1 );
Delta.X = getrandom( -3, 3 );
Delta.Y = getrandom( -3, 3 );
// Set up "happy face" & generate color
// attribute from thread number.
if( *MyID > 16)
MyCell = 0x01; // outline face
else
MyCell = 0x02; // solid face
MyAttrib = *MyID & 0x0F; // force black background
do
{
// Wait for display to be available, then lock it.
WaitForSingleObject( hScreenMutex, INFINITE );
// If we still occupy the old screen position, blank it out.
ReadConsoleOutputCharacter( hConsoleOut, &OldCell, 1,
Old, &Dummy );
ReadConsoleOutputAttribute( hConsoleOut, &OldAttrib, 1,
Old, &Dummy );
if (( OldCell == MyCell ) && (OldAttrib == MyAttrib))
WriteConsoleOutputCharacter( hConsoleOut, &BlankCell, 1,
Old, &Dummy );
// Draw new face, then clear screen lock
WriteConsoleOutputCharacter( 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 >= csbiInfo.dwSize.X )
{
Delta.X = -Delta.X;
Beep( 400, 50 );
}
if( Coords.Y < 0 || Coords.Y > csbiInfo.dwSize.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 = 80
};
char NThreadMsg[sizeOfNThreadMsg];
sprintf_s( NThreadMsg, sizeOfNThreadMsg,
"Threads running: %02d. Press 'A' "
"to start a thread,'Q' to quit.", ThreadNum );
SetConsoleTitle( NThreadMsg );
}
void ClearScreen( void )
{
DWORD dummy;
COORD Home = { 0, 0 }; //控制台座標型態
FillConsoleOutputCharacter( hConsoleOut, ' ',
csbiInfo.dwSize.X * csbiInfo.dwSize.Y,
Home, &dummy ); //設定終端機初始字元
}
資料參考:
http://msdn.microsoft.com/zh-tw/library/esszf9hw(v=vs.80).aspx
http://slimemeteor.blogspot.tw/2010/10/sprintf-and-snprintf-and-buffer.html
http://baike.baidu.com/view/2666640.htm
http://zhidao.baidu.com/question/243419995.html
http://www.dreamincode.net/forums/topic/153240-console-cursor-coordinates/
http://www.programmer-club.com/showSameTitleN/c/28156.html
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682663(v=vs.85).aspx
http://www.cppblog.com/finehai/archive/2012/11/24/90746.html
http://blog.csdn.net/laura0502/article/details/3838732
http://hs.hosp.ncku.edu.tw/~cww/htmapi73.htm
http://bbs.csdn.net/topics/21693
http://www.njustjx.cn/thread-239-1-1.html
http://msdn.microsoft.com/zh-tw/library/kdzttdcb(v=vs.80).aspx
http://msdn.microsoft.com/zh-tw/library/system.threading.mutex.releasemutex(v=vs.80).aspx
http://msdn.microsoft.com/zh-tw/library/windows/desktop/ms685066(v=vs.85).aspx
http://blog.sina.com.cn/s/blog_630e168d0100tfnv.html
http://www.360doc.com/content/10/0512/09/1072296_27178529.shtml
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684969(v=vs.85).aspx
http://hi.baidu.com/console_app/item/0e5e7ad689737111e1f46f00
http://tlcheng.twbbs.org/TLCheng/WinAPI/winapi.asp?action=FunName&FunName=ReadConsoleOutputCharacter
http://bbs.csdn.net/topics/300073601
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687407(v=vs.85).aspx
http://zhidao.baidu.com/question/313723405.html
http://hi.baidu.com/ncudlz/item/341e0df034030ecd521c262e
http://msdn.microsoft.com/zh-tw/library/windows/desktop/ms724211(v=vs.85).aspx