Войти

Показать полную графическую версию : [решено] С++ Builder и потоки (win32 api)


st_dark
17-12-2011, 19:09
При обращении к компоненту из другого потока приложение зависает. Перед обращением первичный поток, создавший компонент переводится в состояние ожидания. Как только код не переписывал, но лучшее, что получилось, - это зависание при втором обращении.
Вот последняя (но не самая лучшая) версия:

struct TThreadParam {
TComponent *owner;
HWND hwnd; // хэндл окна, информацию о котором нужно вывести
};

DWORD WINAPI ThreadProcGeneral (LPVOID lparam) {
TThreadParam *param = (TThreadParam *) lparam;

DWORD error;

HANDLE currentThreadHandle = OpenThread (THREAD_ALL_ACCESS,
FALSE, GetCurrentThreadId());

TComponent *owner = param->owner;
TLabeledEdit *lEdit =
(TLabeledEdit *) owner->FindComponent("leHandle");
// выход пока не нужен, мне бы обновление сделать
while (true) {

HWND hwnd = param->hwnd;
if (owner == NULL || hwnd == NULL) {
continue;
}

lEdit->Text = "0x" + IntToHex((int) hwnd, 8); // вот тут зависает

SetEvent (hEventGeneral);
SuspendThread (currentThreadHandle);
}
return 0;
}

void TMainForm::InitThreads () {
hThreadGeneral = = NULL; // хэндл потока, обновляющего вкладку "Общие"
hThreadGeneral = CreateThread (NULL, 0, ThreadProcGeneral, (LPVOID) &param,
CREATE_SUSPENDED, NULL);
allThreads[0] = hThreadGeneral;
allEventForThreads[0] = hEventGeneral = CreateEvent (NULL, FALSE, FALSE, NULL);
}

void StartUpdate () {
int i;
for (i = 0; i < COUNT_THREADS; i++) {
ResetEvent (allEventForThreads[i]);
}
for (i = 0; i < COUNT_THREADS; i++) {
ResumeThread(allThreads[i]);
}
}

void __fastcall TMainForm::tvWindowsChange(TObject *Sender, TTreeNode *Node)
{
//
DWORD error;
if (Node->Selected == false) return;
param.hwnd = (HWND) Node->Data;

StartUpdate();
DWORD waitStatus = WaitForMultipleObjects (COUNT_THREADS, allEventForThreads,
TRUE, INFINITE);
error = GetLastError();
switch (waitStatus) {
case WAIT_OBJECT_0:
break;
case WAIT_FAILED:
return;
}

}

st_dark
18-12-2011, 11:44
Всё, разобрался. Не надо было первичный поток приостанавливать. Может это и неправильно, но это работает.
void __fastcall TMainForm::tvWindowsChange(TObject *Sender, TTreeNode *Node)
{
if (Node->Selected == false) return;
param.hwnd = (HWND) Node->Data;
StartUpdate();
}
DWORD WINAPI ThreadProcGeneral (LPVOID lparam) {
TThreadParam *param = (TThreadParam *) lparam;
DWORD error;
HANDLE currentThreadHandle = OpenThread (THREAD_ALL_ACCESS,
FALSE, GetCurrentThreadId());
TComponent *owner = param->owner;
TLabeledEdit *lEdit =
(TLabeledEdit *) owner->FindComponent("leHandle");
while (true) {

HWND hwnd = param->hwnd;
if (hwnd == NULL) {
continue;
}

lEdit->Text = "0x" + IntToHex((int) hwnd, 8); // вот тут уже не зависает
SuspendThread (currentThreadHandle);
}
return 0;
}




© OSzone.net 2001-2012