2017-02-03 14 views
-1

私のアプリは10年以上前からワーカースレッドからそのグラフィックスを描画しており、問題は一度もありませんでした。ワーカースレッドは、このような(メインスレッドによって作成された)私のHWNDに描画します。他のプラットフォームへの私のアプリを移植した後子スレッドからのウィンドウへの描画

hdc = GetDC(hwnd); 
SetDIBitsToDevice() ... or StretchDIBits() 
ReleaseDC(hwnd, hdc); 

、私はメインスレッド以外のスレッドから描画することは通常であることを認識し始めました多くのプラットフォーム(例えば、macOS)では動作しません。私の研究によると、これはWin32でも当てはまるかもしれませんが、私はまだ明確な答えが欠けています。

したがって、私の質問:

は、それが描画されたウィンドウを作成しなかったことをワーカースレッドから上に示したように、それは私のウィンドウに描画することができますか?ワーカースレッドは実際にはウィンドウに描画される唯一のスレッドであることに注意してください。メインスレッドは描画を行いません。 WM_PAINTでさえありません。私の場合は、ワーカースレッドが50fpsで描画するので、WM_PAINTに描画する必要はありません。

許可されていない場合は、ワーカースレッドからメインスレッドに描画を委譲する最良の方法は何ですか?

+0

http://stackoverflow.com/questions/5622850/hwnd-thread-affinity-painting-from-a-different-thread – VuVirt

+0

これは間違いなくWin32では間違っていました。もしそれが確実に働いていれば(それはないと思われますが、バグは再現するのが難しい)、事故でした。すべての描画は 'WM_PAINT'期間に応じて行われます。アプリケーションが50 fpsで描画する必要があるのはなぜですか?これが実際に50fpsを必要とするゲームや他の種類の派手なビジネスであれば、おそらくDirectXなどを使用しているはずです。 –

+0

とにかく、このスレッドを複数のスレッドにわたって分散させる必要がある場合は、ワーカースレッドにDIBセクションを準備させてから、 'RedrawWindow'を呼び出すことによってウィンドウを強制的に再描画させます。メインスレッドは 'WM_PAINT'メッセージを受信し、そのメッセージハンドラの内部で、DIBセクションをメッセージと共に受信するDCに描画します。繰り返しますが、ここで複数のスレッドを使って何を買っているのかははっきりしませんが、これでうまくいきます。 –

答えて

1

描画先のウィンドウを作成していないワーカースレッドから上記のように描画することはできますか?

限り、あなたはGetDCための文書化のルールを尊重して、それはあなたの問題を解決する最善ではないかもしれないが、それは安全です:

  • DCへのハンドルが唯一できることに注意してください一度に1つのスレッドで使用されます。
  • ReleaseDCは、GetDCと呼ばれる同じスレッドから呼び出される必要があります。

あなたが複数のスレッドから同じデバイスコンテキストに描画を行う場合、あなたはそれへのアクセスを同期するための責任があります。 *

コメントで説明したように、ワーカースレッドからDIBを生成し、このスレッドにRedrawWindowを呼び出してウィンドウを更新させることをお勧めします。メインスレッドはWM_PAINTハンドラのStretchBltになります。スレッド間でRedrawWindowを呼び出すと、同期バリアが実装されます。呼び出しが戻ると、ターゲットスレッドのレンダリングが完了して実行され、DIBを再利用することは安全です。 *


Thread affinity of user interface objects, part 2: Device contexts
を参照してください。

関連する問題