Поток заморозки приложения - PullRequest
0 голосов
/ 17 мая 2011

Я разрабатываю приложение, которое читает наборы данных DICOM и визуализирует их с помощью методов объемного рендеринга с использованием библиотеки VTK . В любом случае, проблема, с которой я сталкиваюсь, заключается в том, что объемный рендеринг действительно ограничен процессором. Если я обрабатываю рендеринг тома в однопоточном процессе, приложение (GUI) зависает и переходит в состояние «не отвечает». Я написал другой поток для процесса рендеринга тома. Однако GUI все еще зависает, вот коды.

private: System::Void volumeRenderButton_Click(System::Object^  sender, System::EventArgs^  e) {

             volumeRenderThread = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this, &Form1::volumeRender));
             volumeRenderThread->Priority = System::Threading::ThreadPriority::Lowest;
             volumeRenderThread->Start();                                   
         }

private: void volumeRender()
         {
             threeDPictureBox->Invoke(gcnew volumeDelegate(this, &Form1::volumeDelegateMethod));        

             /*
             if ( threeDPictureBox->InvokeRequired )
             {
                threeDPictureBox->Invoke(gcnew System::Action(this, &Form1::volumeRender));
             }
             else
             {
                 dicom->VolumeRender(threeDPictureBox, vrSettings); 
             }
             */
         }
private: delegate void volumeDelegate();

private: void volumeDelegateMethod()
         {
             dicom->VolumeRender(threeDPictureBox, vrSettings); 
         }


void Dicom::VolumeRender( Windows::Forms::PictureBox ^pictureBox, VRsettings *settings )
{
    renderer = vtkSmartPointer < vtkRenderer > :: New();
    renderWindow = vtkSmartPointer < vtkWin32OpenGLRenderWindow > :: New();
    renderWindow->AddRenderer(renderer);
    renderWindow->SetParentId((HWND)((pictureBox->Handle).ToPointer()));
    renderWindow->SetSize(pictureBox->Width, pictureBox->Height);
    renderWindow->Initialize();
    /* A lot of stuff here */
    ...
    ...
    renderWindow->Render();
    iren->Initialize();     // vtkWin32RenderWindowInteractor

}

threeDPictureBox - это компонент PictureBox, который я отправляю в метод volumeRender объекта dicom. vrSettings - это структура для параметров объемного рендеринга.
Когда кнопка Render громкости нажата, и обработчик события click срабатывает, volumeRenderThread запускает и останавливает приложение, даже если я установил его приоритет наименьший! Я также попробовал строки, которые прокомментированы. Ни один из них не работает. Какой смысл мне не хватает ?? Спасибо за ответы с этого момента !!

Ответы [ 3 ]

1 голос
/ 17 мая 2011

Ваш поток вызывается по методу, который немедленно переходит обратно в поток пользовательского интерфейса.

Другими словами, у него есть одно действие: указать потоку пользовательского интерфейса выполнить эту работу.

1 голос
/ 17 мая 2011

Вы просто передаете делегат, выполняющий реальную работу, в ваш поток пользовательского интерфейса для выполнения с этим вызовом на Invoke, поэтому установка приоритета volumeRenderThread не поможет никому.

Вам необходимо переместить как можно больше фактической работы из потока пользовательского интерфейса. В вашем фрагменте написано только /* A lot of stuff here */, поэтому трудно точно сказать, как именно вы должны отделить большую часть работы от того, что должно выполняться в потоке пользовательского интерфейса, но это то, что вам нужно сделать.

0 голосов
/ 17 мая 2011

Можете ли вы попробовать следующее и дайте мне знать, если это работает. Мой C ++ довольно ржавый, но идея в следующем. Я предполагаю, что VTK нужен только HWND, чтобы выполнить свою работу, поэтому вам нужно извлечь HWND в вашем потоке пользовательского интерфейса и затем передать это VTK.

Измените свой код следующим образом (обязательно смените мои C # -измы, если они есть, на надлежащие C ++):

private: System::Void volumeRenderButton_Click(System::Object^  sender, System::EventArgs^  e) 
{
    volumeRenderThread = gcnew System::Threading::Thread(gcnew System::Threading::ParameterizedThreadStart(this, &Form1::volumeRender));
    volumeRenderThread->Priority = System::Threading::ThreadPriority::Lowest;
    volumeRenderThread->Start(pictureBox->Handle);                                   
}

private: void volumeRender(System::Object^  pictureBox)
{
    dicom->VolumeRender((HWND)((System::IntPtr)pictureBox).ToPointer()), vrSettings); 
}

void Dicom::VolumeRender( HWND pictureBox, VRsettings *settings )
{
    renderer = vtkSmartPointer < vtkRenderer > :: New();
    renderWindow = vtkSmartPointer < vtkWin32OpenGLRenderWindow > :: New();
    renderWindow->AddRenderer(renderer);
    renderWindow->SetParentId(pictureBox);
    renderWindow->SetSize(pictureBox->Width, pictureBox->Height);
    renderWindow->Initialize();
    /* A lot of stuff here */
    ...
    ...
    renderWindow->Render();
    iren->Initialize();     // vtkWin32RenderWindowInteractor
} 
...