Многопоточность в lister-plugins
Select messages from
# through # FAQ
[/[Print]\]

Total Commander -> Написание плагинов для Total Commander

#1: Многопоточность в lister-plugins Author: ParcanLocation: Russian PostPosted: Wed Aug 30, 2006 09:52
    —
Предлагаю выкладывать тут примеры или объяснения реализации многопоточности для листер-плагинов на различных языках программирования и с использованием различных средств. Смотри и по умолчанию все так делать начнут.
ЗЫ. заметил, что это реализовано в очень малом числе плагинов.
ЗЫЫ. дома посмотрю выложу простой пример, как это реализовать на visual c++ c использованием событий и оконных сообщений в принципе на чистом WinAPI.

#2:  Author: ParcanLocation: Russian PostPosted: Wed Sep 06, 2006 10:19
    —
Организация анализа файла в рабочем потоке с использованием "События" и "Оконных сообщений" код на 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() если надо происходит установка события чтоб завершыить еще выполняющийся рабочий поток и ожидание его завершения.



Total Commander -> Написание плагинов для Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Page 1 of 1

Powered by phpBB © 2001, 2005 phpBB Group