我正在设计一个应用程序,它使用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会启动并冻结应用程序,即使我已将其优先级设置为最低!我也尝试了评论的行。它们都不起作用。我错过了什么?感谢您的回答!!
答案 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
}