| Parcan 
 
  
 Joined: 15 Dec 2004
 Posts: 399
 Location: Russian
 
 | 
			
				|  (Separately) Posted: Wed Sep 06, 2006 10:19    Post subject: |   |  
				| 
 |  
				| Организация анализа файла в рабочем потоке с использованием "События" и "Оконных сообщений" код на visual c++ чистый WinAPI код порезанный, но впринципе все те 20-30 строк которые отвечают за это тут приведены
 
 
  	  | Quote: |  	  | //ispol'zuemie funkcii
 HWND __stdcall ListLoad(HWND,char*,int) //zagruzka plugina
 void __stdcall ListCloseWindow(HWND)    //zakritie plagina
 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM)   //obrabotshik sobitiy okna plagina
 UINT ComputeThreadProc(LPVOID)  //funkciya proizvodyashaya zapusk otdel'nogo potoka
 int MyClass::Start(LPVOID)  //funkciya zapuskaemaya v rabochem potoke
 
 //zapusk plagina
 HWND __stdcall ListLoad(HWND ParentWin,char* FileToLoad,int ShowFlags)
 {
 try
 {
 HWND hwnd = 0;
 
 //parametri sozdavaemogo ekzemplyara plagina
 GlobalParametr* gp = new GlobalParametr;
 if (!gp->InitialGlobalParametr(FileToLoad, hInst))
 { delete gp; gp = 0; return NULL; }
 
 //testiruem vhodnoy fayal
 if (!MyTestArchive(FileToLoad))
 { delete gp; gp = 0; return NULL; }
 
 //registriruem klass okna plagina
 MyRegisterClass();
 hwnd = InitInstance(ParentWin);
 if (!hwnd)
 { delete gp; gp = 0; return NULL; }
 
 //priceplyaem k nemu nashi parametri etogo ekzemplyara plagina
 ::SetWindowLong(hwnd, 0, (long)gp);
 
 #ifndef _MY_DEBUG
 
 //(rabochiy variant) zapusk analiza fayla v rabochem potoke
 //sozdaem sobitie (dlya zaversheniya rabochego potoka)
 gp->hEventEnd = ::CreateEvent(NULL, FALSE, FALSE, "");
 DWORD ThID;
 gp->DataThread.hWnd        = hwnd;			//okno dlya otpravki soobsheniy iz potoka
 gp->DataThread.hEventEnd   = gp->hEventEnd;//sobitie dlya iskustvennogo okonchaniya rabochego potoka
 gp->DataThread.BeginThread = TRUE;			//v rabochem potoke
 gp->DataThread.Path        = FileToLoad;	//fayl dlya analiza
 //zapusk potoka
 gp->hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ComputeThreadProc, &gp->DataThread, THREAD_PRIORITY_NORMAL, &ThID);
 if(!gp->hThread)
 { if (hwnd) { ::DestroyWindow(hwnd); hwnd = 0; } delete gp; gp = 0; return NULL; }
 
 #else
 
 //(otladochniy variant) zapusk analiza fayla v etomje potoke
 gp->DataThread.hWnd        = 0;
 gp->DataThread.hEventEnd   = 0;
 gp->DataThread.BeginThread = FALSE;			//v tomje potoke
 gp->DataThread.Path        = FileToLoad;	//fayl dlya analiza
 //zapusk analiza (pri rabocem potoke ComputeThreadProc() delaet toje samoe)
 if (gp->pArchData->Start(&gp->DataThread) != TMESSAGE_OK)
 { if (hwnd) { ::DestroyWindow(hwnd); hwnd = 0; } delete gp; gp = 0; return NULL; }
 
 #endif
 
 //Otrisovivaem okno s soobsheniem idet analiz fayla i procentom vipolneniya
 MyShowWindow(hwnd);
 
 return hwnd;
 }
 catch (...)
 { return NULL; }
 }
 
 //zakritie plagina
 void __stdcall ListCloseWindow(HWND ListWin)
 {
 try
 {
 //parametri etogo ekzemplyara plagina
 GlobalParametr* gp = (GlobalParametr*)::GetWindowLong(ListWin, 0);
 
 //ustanavlivaem sobitie okonchaniya rabochego potoka
 //chtob on zavershilsya esli eshe vipolnyaetsya
 ::SetEvent(gp->hEventEnd);
 
 //proveryem/jdem okonchaniya rabochego processa
 DWORD ExitCode;
 if (GetExitCodeThread(gp->hThread, &ExitCode))
 {
 while(ExitCode == STILL_ACTIVE)
 {
 //pri neudache prodoljaem zavershenie dal'she
 if(!GetExitCodeThread(gp->hThread, &ExitCode)) break;
 }
 }
 
 delete gp; gp = 0;
 
 //otchistim parametr i v okne
 ::SetWindowLong(ListWin, 0, (long)0);
 
 ::DestroyWindow(ListWin);
 ::UnregisterClass("TMainClassWindow", hInst);
 }
 catch (...) {;}
 }
 
 //obrabotchik sobitiy okna plagina
 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
 
 switch (message)
 {
 case WM_COMMAND:
 // Parse the menu selections:
 return ::DefWindowProc(hWnd, message, wParam, lParam);
 break;
 
 //soobshenie prisilaemoe iz zapushennogo rabochego potoka
 //zavershenie rabochego potoka
 case WM_THREAD_FINISHED:
 //Teper' mojem risovat' nashe okno plagina normal'no
 break;
 
 //soobshenie prisilaemoe iz zapushennogo rabochego potoka
 //procent vipolneniya v rabochem potoke
 case WM_THREAD_PERCENT:
 //Mojem pokazat' procent vipolneniya rabochego potoka
 break;
 
 case WM_SIZE:
 //pererisivka okna
 break;
 
 case WM_PAINT:
 hdc = ::BeginPaint(hWnd, &ps);
 ::EndPaint(hWnd, &ps);
 break;
 
 default:
 return ::DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
 }
 
 //funkciya zapuskaemaya rabochim potokom
 UINT ComputeThreadProc(LPVOID pParam)
 {
 DataForThread*  dft = (DataForThread*)pParam;
 GlobalParametr* gp  = (GlobalParametr*)::GetWindowLong(dft->hWnd, 0);
 
 gp->pArchData->Start(pParam);
 
 return 0;
 }
 
 //gdeto v zapushennom rabochem potoke (naprimer v vizvannoy funkcii Start(LPVOID))
 int MyClass::Start(LPVOID lpDataThread)
 {
 DataForThread* MyDataThread = (DataForThread*)lpDataThread;
 
 //idet ofigenniy analiz fayla dopustim v cikle
 while(TRUE)
 {
 //esli rabochiy potok
 if (MyDataThread->BeginThread)
 {
 //procent vipolneniya raboti
 MyPercent = MyGetPercent();
 ::PostMessage(MyDataThread->hWnd, WM_THREAD_PERCENT, 0, (LPARAM)MyPercent);
 //net li sobitiya zavershit' rabotu potoka
 if(::WaitForSingleObject(MyDataThread->hEventEnd, 0) == WAIT_OBJECT_0)
 {::PostMessage(MyDataThread->hWnd, WM_THREAD_FINISHED, 0, (LPARAM)MyMSG);
 break;}
 }
 //moy krutoy analiz fayla
 MyAnalizeFile();
 }
 
 //esli rabochiy potok otmetim zavershenie
 if (MyDataThread->BeginThread)
 {
 ::PostMessage(MyDataThread->hWnd, WM_THREAD_FINISHED, 0, (LPARAM)MyMSG);
 }
 }
 
 | 
 
 в ListLoad() идет создание события для искуственного завершения рабочего потока и запуск функции Start() в рабочем потоке завернутый в ComputeThreadProc(), в функции Start() идет отправка оконных сообщений о проценте выполнения функции и проверяется событие об искуственном завершении рабочего потока, в WndProc() обрабатываются сообщения в том числе и от рабочего потока, в ListCloseWindow() если надо происходит установка события чтоб завершыить еще выполняющийся рабочий поток и ожидание его завершения.
 |  |