2017-02-03 52 views
-1

我的應用程序從工作線程繪製圖形超過10年,現在我從來沒有遇到過任何問題。工作線程吸引到我的HWND(由主線程創建的)是這樣的:從子線程繪製到窗口

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

已經移植我的應用到其它平臺後,我開始意識到,任何其他線程比主線程繪圖通常是禁止在許多平臺上(例如macOS)。我的研究表明,Win32也可能是這樣,但我仍然缺乏明確的答案。

因此,我的問題:

是否允許吸取我的窗前,彷彿從工作線程沒有創建它畫到窗口上面顯示?請注意,工作線程真的是繪製到窗口的唯一線程。主線程不執行任何繪圖。甚至沒有在WM_PAINT。在我的情況下,在WM_PAINT中繪製是不必要的,因爲工作線程以50fps繪製。

如果不允許,將繪圖從工作線程委託給主線程的最佳方法是什麼?

+0

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

+0

這是絕對錯誤的Win32,並一直是。如果它可靠地工作(我懷疑它沒有,這些錯誤很難重現),這是一個意外。所有繪圖都應該在響應'WM_PAINT'時段內完成。爲什麼應用程序需要以50 fps的速度繪製?如果這是一款遊戲或者其他一些實際需要50 fps的奇特業務,那麼您應該使用DirectX或其他任何類型的遊戲。 –

+0

無論如何,如果你必須做到這一點遍佈多個線程:讓你的工作線程準備DIB部分,然後讓它通過調用'RedrawWindow'來強制窗口立即重繪。然後主線程將收到一條「WM_PAINT」消息,並在該消息處理程序內部,將DIB部分與消息一起繪製到您收到的DC中。再次,目前還不清楚使用多線程在這裏購買了什麼,但這會使它工作。 –

回答

1

它是否可以像上面顯示的那樣從一個工作線程繪製到我的窗口中,該線程不會創建它正在繪製的窗口?

這可能不是你的問題的最佳解決方案,但是當你尊重記錄規則GetDC它是安全的,只要:

  • 注意,句柄DC只能是任何時候都由單個線程使用。
  • ReleaseDC必須從調用GetDC的同一線程調用。

如果渲染到從多個線程在同一設備上下文,你是負責同步訪問它。 *

正如評論中所述,更好的解決方案是從工作者線程生成DIB,並通過調用RedrawWindow來更新窗口。主線程然後可以在WM_PAINT處理程序中使用StretchBlt。跨線程調用RedrawWindow實現同步屏障。當調用返回時,目標線程上的渲染已完成,並且可以安全地重新使用DIB。


* Thread affinity of user interface objects, part 2: Device contexts