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は、dicomオブジェクトのvolumeRenderメソッドに送っているPictureBoxコンポーネントです。vrSettings は、ボリューム レンダリング パラメータの構造体です。
ボリューム レンダリング ボタンがクリックされ、クリック イベント ハンドラーが起動されると、ボリューム レンダー スレッドが開始され、優先度を最低に設定していてもアプリケーションがフリーズします。コメントされている行も試しました。それらのどれも機能しません。私が見逃しているポイントは何ですか?? 今から答えてくれてありがとう!!

4

3 に答える 3

1

実際の作業を UI スレッドに戻してその呼び出しで実行するデリゲートを渡しているだけなInvokeので、優先度を設定しても何の役にvolumeRenderThreadも立ちません。

実際の作業はできるだけ UI スレッドから移動する必要があります。あなたのスニップは/* A lot of stuff here */、UIスレッドで実行する必要があるものからほとんどの作業を分離する方法を正確に提案するのは難しいと言っているだけですが、それはあなたがする必要があることです.

于 2011-05-17T04:21:42.983 に答える
1

スレッドは、すぐに UI スレッドに戻るメソッドで呼び出されます。

つまり、UI スレッドに処理を指示するという 1 つのアクションがあります。

于 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 に答える