线程冻结应用程序

时间:2011-05-17 04:04:11

标签: .net multithreading visual-c++ c++-cli vtk

我正在设计一个应用程序,它使用DICOM库读取VTK数据集并使用体积渲染技术对它们进行可视化。无论如何,我正在处理的问题是体积渲染实际上是CPU限制的过程。如果我在单线程进程中处理卷呈现,应用程序(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组件,我将它发送到dicom对象的volumeRender方法。 vrSettings是体积渲染参数的结构。
单击音量渲染按钮并单击事件处理程序时,volumeRenderThread会启动并冻结应用程序,即使我已将其优先级设置为最低!我也尝试了评论的行。它们都不起作用。我错过了什么?感谢您的回答!!

3 个答案:

答案 0 :(得分:1)

您只是将执行实际工作的委托传递回您的UI线程,以便通过对Invoke的调用执行,因此设置volumeRenderThread的优先级对任何人都没有帮助。

您需要尽可能多地将实际工作移出UI线程。你的剪辑只说/* A lot of stuff here */因此很难确切地说明你应该如何将大部分工作与必须在UI线程上运行的东西分开,但这就是你需要做的事情。

答案 1 :(得分:1)

在一个立即跳回UI线程的方法上调用您的线程。

换句话说,它有一个动作:告诉UI线程完成工作。

答案 2 :(得分:0)

您可以尝试以下操作,让我知道它是否有效。我的C ++很生疏,但想法如下。我猜测VTK只需要HWND来完成它的工作,所以你需要在你的UI线程中检索HWND然后将它传递给VTK。

像这样更改代码(确保将C#isms更改为正确的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
}