windows 线程间通信。如何向另一个线程发送信号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1977742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:40:03  来源:igfitidea点击:

Inter-thread communication. How to send a signal to another thread

c++windowsmultithreadingsignals

提问by Etan

In my application I have two threads

在我的应用程序中,我有两个线程

  1. a "main thread" which is busy most of the time
  2. an "additional thread" which sends out some HTTP request and which blocks until it gets a response.
  1. 大部分时间都很忙的“主线程”
  2. 一个“附加线程”,它发出一些 HTTP 请求并阻塞直到它得到响应。

However, the HTTP response can only be handled by the main thread, since it relies on it's thread-local-storage and on non-threadsafe functions.

然而,HTTP 响应只能由主线程处理,因为它依赖于它的线程本地存储和非线程安全函数。

I'm looking for a way to tell the main thread when a HTTP response was received and the corresponding data. The main thread should be interrupted by the additional thread and process the HTTP response as soon as possible, and afterwards continue working from the point where it was interrupted before.

我正在寻找一种方法来告诉主线程何时收到 HTTP 响应和相应的数据。主线程应该被附加线程中断并尽快处理HTTP响应,然后从之前中断的点继续工作。

  • One way I can think about is that the additional thread suspends the main thread using SuspendThread, copies the TLS from the main thread using some inline assembler, executes the response-processing function itself and resumes the main thread afterwards.

  • Another way in my thoughts is, setting a break point onto some specific address in the second threads callback routine, so that the main thread gets notified when the second threads instruction pointer steps on that break point - and therefore - has received the HTTP response.

  • 我能想到的一种方法是,附加线程使用 挂起主线程SuspendThread,使用一些内联汇编器从主线程复制 TLS,执行响应处理函数本身,然后恢复主线程。

  • 我认为的另一种方法是,在第二个线程回调例程中的某个特定地址上设置一个断点,以便当第二个线程指令指针踩到该断点时主线程得到通知 - 因此 - 已收到 HTTP 响应。

However, both methods don't seem to be nicely at all, they hurt even if just thinking about them, and they don't look really reliable.

不过,这两种方法似乎都不太妙,想想都觉得很痛,看起来也不太靠谱。

What can I use to interrupt my main thread, saying it that it should be polite and process the HTTP response before doing anything else? Answers without dependencies on libraries are appreciated, but I would also take some dependency, if it provides some nice solution.

我可以用什么来中断我的主线程,说它应该礼貌并在做任何其他事情之前处理 HTTP 响应?感谢不依赖库的答案,但如果它提供了一些不错的解决方案,我也会依赖一些。

Following question(regarding the QueueUserAPC solution) was answered and explained that there is no safe method to have a push-behaviour in my case.

以下问题(关于 QueueUserAPC 解决方案)得到回答并解释说,在我的情况下没有安全的方法来进行推送行为。

采纳答案by Brian Cline

This may be one of those times where one works themselves into a very specific idea without reconsidering the bigger picture. There is no singular mechanism by which a single thread can stop executing in its current context, go do something else, and resume execution at the exact line from which it broke away. If it were possible, it would defeat the purpose of having threads in the first place. As you already mentioned, without stepping back and reconsidering the overall architecture, the most elegant of your options seems to be using another thread to wait for an HTTP response, have it suspend the main thread in a safe spot, process the response on its own, then resume the main thread. In this scenario you might rethink whether thread-local storage still makes sense or if something a little higher in scope would be more suitable, as you could potentially waste a lot of cycles copying it every time you interrupt the main thread.

这可能是人们在不重新考虑大局的情况下将自己投入到一个非常具体的想法的时代之一。没有单一的机制可以让单个线程在其当前上下文中停止执行,去做其他事情,并在它脱离的确切行处恢复执行。如果可能的话,它首先会破坏拥有线程的目的。正如您已经提到的,无需退后一步重新考虑整体架构,最优​​雅的选择似乎是使用另一个线程来等待 HTTP 响应,让它将主线程挂起在安全的位置,自行处理响应,然后恢复主线程。在这种情况下,您可能会重新考虑线程本地存储是否仍然有意义,或者范围更大的存储是否更合适,

回答by John Knoeller

What you are describing is what QueueUserAPCdoes. But The notion of using it for this sort of synchronization makes me a bit uncomfortable. If you don't know that the main thread is in a safeplace to interrupt it, then you probably shouldn't interrupt it.

您所描述的是QueueUserAPC 的作用。但是将它用于这种同步的想法让我有点不舒服。如果您不知道主线程在安全的地方可以中断它,那么您可能不应该中断它。

I suspect you would be better off giving the main thread's work to another thread so that it can sit and wait for you to send it notifications to handle work that only it can handle.

我怀疑你最好将主线程的工作交给另一个线程,这样它就可以坐等你向它发送通知来处理只有它才能处理的工作。

PostMessageor PostThreadMessageusually works really well for handing off bits of work to your main thread. Posted messages are handled before user input messages, but not until the thread is ready for them.

PostMessage或者PostThreadMessage通常非常适合将一些工作交给主线程。发布的消息在用户输入消息之前处理,但直到线程为它们准备好后才处理。

回答by Mark Wilkins

I might not understand the question, but CreateSemaphoreand WaitForSingleObjectshould work. If one thread is waiting for the semaphore, it will resume when the other thread signals it.

我可能不明白这个问题,但CreateSemaphoreWaitForSingleObject应该可以工作。如果一个线程正在等待信号量,它会在另一个线程发出信号时恢复。

Update based on the comment: The main thread can call WaitForSingleObject with a wait time of zero. In that situation, it will resume immediately if the semaphore is not signaled. The main thread could then check it on a periodic basis.

根据评论更新:主线程可以在等待时间为零的情况下调用 WaitForSingleObject。在这种情况下,如果信号量没有发出信号,它将立即恢复。然后主线程可以定期检查它。

回答by Oleg Zhylin

If your main thread is GUI thread why not send a Windows message to it? That what we all do to interact with win32 GUI from worker threads.

如果您的主线程是 GUI 线程,为什么不向它发送 Windows 消息?这就是我们从工作线程与 win32 GUI 交互所做的一切。

回答by cheez

One way to do this that is determinate is to periodically check if a HTTP response has been received.

一种确定的方法是定期检查是否已收到 HTTP 响应。

It's better for you to say what you're trying to accomplish.

你最好说出你想要实现的目标。

回答by Jonathan Leffler

It looks like the answer should be discoverable from Microsoft's MSDN. Especially from this section on 'Synchronizing Execution of Multiple Threads'

看起来答案应该可以从 Microsoft 的MSDN 中找到。尤其是关于“同步执行多线程”的这一节

回答by Beanz

In this situation I would do a couple of things. First and foremost I would re-structure the work that the main thread is doing to be broken into as small of pieces as possible. That gives you a series of safe places to break execution at. Then you want to create a work queue, probably using the microsoft slist. The slist will give you the ability to have one thread adding while another reads without the need for locking.

在这种情况下,我会做几件事。首先,我会重新构建主线程正在执行的工作,以便将其分解成尽可能小的部分。这为您提供了一系列安全的地方来中断执行。然后你想创建一个工作队列,可能使用 microsoft slist。slist 将使您能够在不需要锁定的情况下添加一个线程而另一个读取。

Once you have that in place you can essentially make your main thread run in a loop over each piece of work, checking periodically to see if there are requests to handle in the queue. Long-term what is nice about an architecture like that is that you could fairly easily eliminate the thread localized storage and parallelize the main thread by converting the slist to a work queue (probably still using the slist), and making the small pieces of work and the responses into work objects which can be dynamically distributed across any available threads.

一旦你有了它,你基本上可以让你的主线程在每一项工作中循环运行,定期检查队列中是否有需要处理的请求。从长远来看,这样的架构的好处在于,您可以相当容易地消除线程本地化存储并通过将 slist 转换为工作队列(可能仍在使用 slist)并制作小块工作来并行化主线程以及对可以跨任何可用线程动态分布的工作对象的响应。