Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] С++ Builder и потоки (win32 api) (http://forum.oszone.net/showthread.php?t=223150)

st_dark 17-12-2011 19:09 1816977

С++ Builder и потоки (win32 api)
 
При обращении к компоненту из другого потока приложение зависает. Перед обращением первичный поток, создавший компонент переводится в состояние ожидания. Как только код не переписывал, но лучшее, что получилось, - это зависание при втором обращении.
Вот последняя (но не самая лучшая) версия:

Код:

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 1817272

Всё, разобрался. Не надо было первичный поток приостанавливать. Может это и неправильно, но это работает.
Код:

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;
}



Время: 15:54.

Время: 15:54.
© OSzone.net 2001-