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