困っています。Application.DoEventsを使用してApplication.Runの呼び出しをエミュレートしようとしています...これは悪いように聞こえますが、質問に対する代替ソリューションも受け入れます...
Application.Runのようにメッセージポンプを処理する必要がありますが、メッセージ処理の前後にコードを実行する必要があります。これがコードの主な重要なスニペットです。
// Create barrier (multiple kernels synchronization)
sKernelBarrier = new KernelBarrier(sKernels.Count);
foreach (RenderKernel k in sKernels) {
// Create rendering contexts (one for each kernel)
k.CreateRenderContext();
// Start render kernel kernels
k.mThread = new Thread(RenderKernelMain);
k.mThread.Start(k);
}
while (sKernelBarrier.KernelCount > 0) {
// Wait untill all kernel loops has finished
sKernelBarrier.WaitKernelBarrier();
// Do application events
Application.DoEvents();
// Execute shared context services
foreach (RenderKernelContextService s in sContextServices)
s.Execute(sSharedContext);
// Next kernel render loop
sKernelBarrier.ReleaseKernelBarrier();
}
このコードスニペットは、メインルーチンによって実行されます。実は、別々のスレッドで実行されるカーネルクラスのリストがあります。これらのスレッドは、OpenGLでレンダリングするためのフォームを処理します。バリアを使用してすべてのカーネルスレッドを同期する必要がありますが、これは完全に機能します。もちろん、作成されたすべてのフォームについて、メインスレッド(メインルーチン)でフォームメッセージを処理する必要があります。実際、Application.DoEvents()を呼び出してジョブを実行します。
ここで、上記のスニペットを変更して、Application.RunのようにApplication.DoEvents()を呼び出すCPUを100%消費せずに、共通のフォーム(単純なダイアログボックス)を作成する必要があります。
目標は、上記のスニペットが到着時にメッセージを処理し、最大FPSを取得しようとせずに、必要な場合にのみレンダリングを発行する(バリアを解放する)ことです。可能な限りレンダリングするために、厳密なループに切り替える可能性があるはずです。
どうしてそれが可能でしょうか?
注:OpenGLコンテキストはメインスレッドで作成されるため、上記のスニペットはメインルーチンで実行する必要があります。別のスレッドでスニペットを移動し、Application.Runを呼び出すと、非常に不安定でバグが発生します...