天天看點

window線程池

window提供了線程池機制,友善開發。這些線程池函數允許我們做以下事情: 1.以異步方式來調用一個函數。 2.每個一段時間調用一個函數 3.當核心對象觸發時調用一個函數 4.當異步IO請求完成時調用一個函數

一、以異步方式調用一個函數: 相關API:TrySubmitThreadPoolCallback 回調函數原型:VOID NTAPI SimpleCallback(PTP_CALLBACK_INSTANCE pInstance,PVOID pvContext) 簡單的封裝,免得每次使用都要記住api和回調函數的原型。 class IAsOpThread { public: virtual void ThreadProc() = 0; bool Start() { //TrySubmitThreadpoolCallback 可能失敗,這時候線程不會被啟動,是以這裡重試 int tryCount = 0; bool ret = TrySubmitThreadpoolCallback(IAsOpThread::SimpleCallback, this, NULL); while (!ret && tryCount < 3) { ret = TrySubmitThreadpoolCallback(IAsOpThread::SimpleCallback, this, NULL); ++tryCount; } return ret; }

private: static VOID CALLBACK SimpleCallback(PTP_CALLBACK_INSTANCE Instance, PVOID pContext) { static_cast<IAsOpThread*>(pContext)->ThreadProc(); } };

class NormalWork: public IAsOpThread { public: NormalWork() {} ~NormalWork() {}

void ThreadProc() override { cout << "NormalWork" << endl; } };

int _tmain(int argc, _TCHAR* argv[]) { NormalWork normalWork; normalWork.Start(); system("pause"); return 0; }

顯示控制工作項 TrySubmitThreadpoolCallback調用時,系統會配置設定一個工作項,如果需要頻繁送出大量工作項,對于性能和記憶體使用的考慮,我們可以建立一個工作項,然後分多次送出。之前的項目中需要頻繁的計算檔案塊的校驗資訊,由于計算校驗資訊的算法邏輯時一樣的,每次送出請求隻是設定個别參數即可。這時就适用這種方式。

class IAsOpThread { public: virtual void ThreadProc() = 0; virtual ~IAsOpThread() { CloseThreadpoolWork(m_pwk); } bool Start() { m_pwk = CreateThreadpoolWork(IAsOpThread::WorkCallback, this, NULL); SubmitThreadpoolWork(m_pwk); Sleep(1000); return true; }

private:

static VOID CALLBACK WorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID pContext, PTP_WORK Work) { static_cast<IAsOpThread*>(pContext)->ThreadProc(); } PTP_WORK m_pwk; };

class NormalWork: public IAsOpThread { public: NormalWork() {} ~NormalWork() {} void SetFileOffset(int offset) { m_offset = offset; }

void ThreadProc() override { cout << "current threadid :" << GetCurrentThreadId() << endl; cout << "offset:" << m_offset << endl; cout << "calc verify info" << endl; }

private: int m_offset{0}; }; int _tmain(int argc, _TCHAR* argv[]) { NormalWork normalWork; cout << "start work" << endl; normalWork.Start(); normalWork.SetFileOffset(100); normalWork.Start(); normalWork.SetFileOffset(200); normalWork.Start(); system("pause"); return 0; }

二、每隔一段時間調用一個函數 相關api: CreateThreadpoolTimer, SetThreadpoolTimer, IsThreadpoolTimerSet, WaitForThreadpoolTimerCallbacks, CloseThreadpoolTimer 回調函數的原型: VOID CALLBACK TimerCallback( [ in , out ] PTP_CALLBACK_INSTANCE Instance, [ in , out , optional] PVOID Context, [ in , out ] PTP_TIMER Timer );

class ThreadPoolTimer { public:

virtual ~ThreadPoolTimer() { KillTimer(); }

virtual void WorkProc() { cout << "base timer do nothing" << endl; } void SetTimer(int dueTime,int period) { m_pTimer = CreateThreadpoolTimer(ThreadPoolTimer::TimerCallback, this, NULL); ULARGE_INTEGER ulRelativeStartTime; ulRelativeStartTime.QuadPart = (LONGLONG)-dueTime * 100000*100; FILETIME ftRelativeStartTime; ftRelativeStartTime.dwHighDateTime = ulRelativeStartTime.HighPart; ftRelativeStartTime.dwLowDateTime = ulRelativeStartTime.LowPart; SetThreadpoolTimer(m_pTimer, &ftRelativeStartTime, period * 1000, 0); }

bool IsTimerSet() { return m_pTimer && IsThreadpoolTimerSet(m_pTimer); }

void KillTimer() { if (m_pTimer) { CloseThreadpoolTimer(m_pTimer); } } private:

static VOID CALLBACK TimerCallback(PTP_CALLBACK_INSTANCE Instance, PVOID pContext, PTP_TIMER Timer) { static_cast<ThreadPoolTimer*>(pContext)->WorkProc(); } PTP_TIMER m_pTimer{NULL}; }; int _tmain(int argc, _TCHAR* argv[]) { ThreadPoolTimer threadTimer; threadTimer.SetTimer(3, 0); system("pause"); return 0; }

三、中核心對象被觸發時調用一個函數 回調函數原型 VOID CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE pInstance,PVOID Context, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult); 相關api:CreateThreadPoolWait,SetThreadPoolWait, 線程池中内部會讓一個線程調用WaitForMultipleObjects函數,傳入通過SetThreadPoolWait注冊的一組句柄。由于WaitForMultipleObjects不允許我們将同一個句柄傳入多次,是以我們必須確定不會SetThreadPoolWait來多次注冊一個句柄。

VOID CALLBACK WaitCallbackWorkThread(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult) { cout << "this is a WaitCallback fun" << endl;; }

int _tmain(int argc, _TCHAR* argv[]) { PTP_WAIT pw = CreateThreadpoolWait(WaitCallbackWorkThread, NULL, NULL); HANDLE h = CreateEvent(NULL, TRUE, FALSE, NULL); SetThreadpoolWait(pw, h, NULL); Sleep(3000); //觸發核心對象 SetEvent(h); WaitForThreadpoolWaitCallbacks(pw, TRUE); CloseThreadpoolWait(pw); CloseHandle(h); system("pause"); return 0; }

四、中異步IO請求完成時調用一個函數 回調函數原型: VOID CALLBACK overlappedCompletionRoutine(PTP_CALLBACK_INSTANCE pInstance, UNLOG IoResult,ULONG_PTR NumberOfBytesTransferred,PTP_IO pIo) 相關api: CreateThreadpoolIo, StartThreadpoolIo, CancelThreadpoolIo, CloseThreadpoolIo, WaitForThreadpoolIoCallbacks。 VOID CALLBACK IoCompletionWorkThread4(PTP_CALLBACK_INSTANCE Instance, PVOID Context, PVOID Overlapped, ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO Io) { cout<<"this is a IoCompletionCallback fun"<<endl; }

int _tmain(int argc, _TCHAR* argv[]) { //打開D盤下檔案a.txt HANDLE h = CreateFile(_T("D:\\log_network.txt"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL); PTP_IO pi = CreateThreadpoolIo(h, IoCompletionWorkThread4, NULL, NULL); StartThreadpoolIo(pi); OVERLAPPED ol; ZeroMemory(&ol, sizeof(OVERLAPPED)); char c[1024] = {0}; DWORD readbytes = 0; if (!ReadFile(h, c, 1024, &readbytes, &ol)) { if (ERROR_IO_PENDING != GetLastError()) { CancelThreadpoolIo(pi); } } Sleep(2000); WaitForThreadpoolIoCallbacks(pi, TRUE); CloseThreadpoolIo(pi); system("pause"); return 0; }