处理消息太慢,导致生涩,无响应的用户界面 - 如何使用多个线程来缓解这种情况?

时间:2021-08-22 20:55:21

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.

在处理长操作时创建单独的线程,即保持简单,问题在于您运行的某些代码花费的时间太长,这是应该有一个单独线程的代码。

#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.

在处理长操作时创建单独的线程,即保持简单,问题在于您运行的某些代码花费的时间太长,这是应该有一个单独线程的代码。