简体   繁体   English

线程间通信。如何将信号发送到另一个线程

[英]Inter-thread communication. How to send a signal to another thread

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. 一个“附加线程”,它发出一些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. 我正在寻找一种方法来告诉主线程何时收到HTTP响应和相应的数据。 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响应,然后继续从之前中断的点开始工作。

  • 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. 我可以考虑的另一种方法是附加线程使用SuspendThread挂起主线程,使用一些内联汇编器从主线程复制TLS,执行响应处理函数本身并在之后恢复主线程。

  • 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. 我想到的另一种方法是,在第二个线程回调例程中的某个特定地址上设置一个断点,这样当第二个线程指令指针在该断点上步进时,主线程就会收到通知 - 因此 - 已收到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? 我可以用什么来打断我的主线程 ,说它应该礼貌并在做其他事情之前处理HTTP响应? Answers without dependencies on libraries are appreciated, but I would also take some dependency, if it provides some nice solution. 我们赞赏没有依赖库的答案,但如果它提供了一些很好的解决方案,我也会采取一些依赖。

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解决方案)得到了解答,并解释说在我的案例中没有安全的方法来推动行为。

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. 正如您已经提到的,没有退回并重新考虑整体架构,您最优雅的选择似乎是使用另一个线程等待HTTP响应,让它将主线程暂停在安全位置,自己处理响应,然后恢复主线程。 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. 在这种情况下,您可能会重新考虑线程本地存储是否仍然有意义,或者更高范围内的某些内容是否更合适,因为每次中断主线程时,您可能会浪费大量的周期来复制它。

What you are describing is what QueueUserAPC does. 你所描述的是QueueUserAPC的作用。 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 safe place to interrupt it, then you probably shouldn't interrupt it. 如果您不知道主线程在安全的地方中断它,那么您可能不应该打断它。

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. 我怀疑你最好将主线程的工作交给另一个线程,以便它可以等待你发送通知来处理它只能处理的工作。

PostMessage or PostThreadMessage usually works really well for handing off bits of work to your main thread. PostMessagePostThreadMessage通常可以很好地将一些工作分配给主线程。 Posted messages are handled before user input messages, but not until the thread is ready for them. 发布消息在用户输入消息之前处理,但直到线程为它们做好准备。

I might not understand the question, but CreateSemaphore and WaitForSingleObject should work. 我可能不理解这个问题,但CreateSemaphoreWaitForSingleObject应该可以工作。 If one thread is waiting for the semaphore, it will resume when the other thread signals it. 如果一个线程正在等待信号量,它将在另一个线程发出信号时恢复。

Update based on the comment: The main thread can call WaitForSingleObject with a wait time of zero. 基于注释更新:主线程可以调用WaitForSingleObject,等待时间为零。 In that situation, it will resume immediately if the semaphore is not signaled. 在那种情况下,如果信号量没有发出信号,它将立即恢复。 The main thread could then check it on a periodic basis. 然后主线程可以定期检查它。

It looks like the answer should be discoverable from Microsoft's MSDN . 看起来应该可以从微软的MSDN中找到答案。 Especially from this section on ' Synchronizing Execution of Multiple Threads ' 特别是关于“ 同步执行多个线程 ”的这一节

If your main thread is GUI thread why not send a Windows message to it? 如果您的主线程是GUI线程,为什么不向它发送Windows消息? That what we all do to interact with win32 GUI from worker threads. 我们所做的就是从工作线程与win32 GUI进行交互。

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. 你最好说出你想要完成的事情。

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. 然后你想创建一个工作队列,可能使用microsoft slist。 The slist will give you the ability to have one thread adding while another reads without the need for locking. 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)并轻松地消除线程本地化存储并并行化主线程,并使小块工作以及可以跨任何可用线程动态分布的工作对象的响应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM