那我找到是這個,就參考底下的範例去分析吧!
依依瞭解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