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() если надо происходит установка события чтоб завершыить еще выполняющийся рабочий поток и ожидание его завершения. |
|