處理消息太慢,導致生澀,無響應的用戶界面 - 如何使用多個線程來緩解這種情況?

[英]Processing messages is too slow, resulting in a jerky, unresponsive UI - how can I use multiple threads to alleviate this?


I'm having trouble keeping my app responsive to user actions. Therefore, I'd like to split message processing between multiple threads.

我無法讓我的應用響應用戶操作。因此,我想在多個線程之間拆分消息處理。

Can I simply create several threads, reading from the same message queue in all of them, and letting which ever one is able process each message?

我可以簡單地創建多個線程,從所有線程中讀取相同的消息隊列,並讓哪一個能夠處理每條消息?

If so, how can this be accomplished?

如果是這樣,怎么能實現呢?

If not, can you suggest another way of resolving this problem?

如果沒有,你能提出另一種解決這個問題的方法嗎?

3 个解决方案

#1


You cannot have more than one thread which interacts with the message pump or any UI elements. That way lies madness.

您不能有多個與消息泵或任何UI元素交互的線程。那種方式就是瘋狂。

If there are long processing tasks which can be farmed out to worker threads, you can do it that way, but you'll have to use another thread-safe queue to manage them.

如果有很長的處理任務可以用於工作線程,那么你可以這樣做,但是你必須使用另一個線程安全的隊列來管理它們。

#2


If this were later in the future, I would say use the Asynchronous Agents APIs (plug for what I'm working on) in the yet to be released Visual Studio 2010 however what I would say given todays tools is to separate the work, specifically in your message passing pump you want to do as little work as possible to identify the message and pass it along to another thread which will process the work (hopefully there isn't Thread Local information that is needed). Passing it along to another thread means inserting it into a thread safe queue of some sort either locked or lock-free and then setting an event that other threads can watch to pull items from the queue (or just pull them directly). You can look at using a 'work stealing queue' with a thread pool for efficiency.

如果這是將來的后期,我會說在尚未發布的Visual Studio 2010中使用異步代理API(插件用於我正在處理的內容)但是我今天所說的工具是分開工作,特別是在您的消息傳遞泵中,您希望盡可能少地工作以識別消息並將其傳遞給另一個將處理工作的線程(希望不存在所需的線程本地信息)。將它傳遞給另一個線程意味着將其插入到某種線程安全隊列中,無論是鎖定還是無鎖,然后設置其他線程可以監視從隊列中提取項目的事件(或者直接拉動它們)。您可以使用帶有線程池的“工作竊取隊列”來提高效率。

This will accomplish getting the work off the UI thread, to have the UI thread do additional work (like painting the results of that work) you need to generate a windows message to wake up the UI thread and check for the results, an easy way to do this is to have another 'work ready' queue of work objects to execute on the UI thread. imagine an queue that looks like this: threadsafe_queue<function<void(void)> basically you can check if it to see if it is non-empty on the UI thread, and if there are work items then you can execute them inline. You'll want the work objects to be as short lived as possible and preferably not do any blocking at all.

這將完成UI線程的工作,讓UI線程做額外的工作(比如繪制工作的結果),你需要生成一個窗口消息來喚醒UI線程並檢查結果,一個簡單的方法要做到這一點,就要在UI線程上執行另一個“工作就緒”工作對象隊列。想象一個看起來像這樣的隊列:threadsafe_queue 基本上你可以檢查它是否在UI線程上看是否為非空,如果有工作項,那么你可以內聯執行它們。您希望工作對象盡可能短暫,並且最好不要進行任何阻塞。

Another technique that can help if you are still seeing jerky movement responsiveness is to either ensure that you're thread callback isn't executing longer that 16ms and that you aren't taking any locks or doing any sort of I/O on the UI thread. There's a series of tools that can help identify these operations, the most freely available is the 'windows performance toolkit'.

如果你仍然看到不穩定的運動響應能力,另一種技術可以幫助確保你的線程回調沒有執行16ms的更長時間,並且你沒有在UI上進行任何鎖定或進行任何類型的I / O操作線。有一系列工具可以幫助識別這些操作,最免費的是“Windows性能工具包”。

#3


Create the separate thread when processing the long operation i.e. keep it simple, the issue is with some code you are running that is taking too long, that's the code that should have a separate thread.

在處理長操作時創建單獨的線程,即保持簡單,問題在於您運行的某些代碼花費的時間太長,這是應該有一個單獨線程的代碼。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/04/23/729948a4a60d4783dc0ead44d4b3ce98.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com