0

我正在设计一个应用程序,它读取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 也会启动并冻结应用程序!我也尝试过评论的行。它们都不起作用。我错过了什么?感谢您从现在开始的答案!

4

3 回答 3

1

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

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

于 2011-05-17T04:21:42.983 回答
1

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

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

于 2011-05-17T04:22:32.797 回答
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
} 
于 2011-05-17T04:57:30.870 回答