Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Многопоточность в lister-plugins

 
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
Parcan



Joined: 15 Dec 2004
Posts: 399
Location: Russian

Post (Separately) Posted: Wed Aug 30, 2006 09:52    Post subject: Многопоточность в lister-plugins Reply with quote

Предлагаю выкладывать тут примеры или объяснения реализации многопоточности для листер-плагинов на различных языках программирования и с использованием различных средств. Смотри и по умолчанию все так делать начнут.
ЗЫ. заметил, что это реализовано в очень малом числе плагинов.
ЗЫЫ. дома посмотрю выложу простой пример, как это реализовать на visual c++ c использованием событий и оконных сообщений в принципе на чистом WinAPI.
Back to top
View user's profile Send private message
Parcan



Joined: 15 Dec 2004
Posts: 399
Location: Russian

Post (Separately) Posted: Wed Sep 06, 2006 10:19    Post subject: Reply with quote

Организация анализа файла в рабочем потоке с использованием "События" и "Оконных сообщений" код на 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() если надо происходит установка события чтоб завершыить еще выполняющийся рабочий поток и ожидание его завершения.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group