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?
You cannot have more than one thread which interacts with the message pump or any UI elements. That way lies madness.
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.
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.
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性能工具包”。
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.