【问题标题】:Ensure thread has started winapi c++确保线程已启动 winapi c++
【发布时间】:2014-07-01 14:47:05
【问题描述】:

我正在使用 c++ 中的 winapi 创建一个程序。该程序涉及两个线程。我使用 CreateThread 创建了一个线程。问题是 CreateThread 在创建线程之前不会阻塞。这会导致问题,因为我在线程之间发送消息,并且线程在创建线程之前不会收到任何消息。如何解决这个问题。

【问题讨论】:

  • 为什么不等待来自新线程的一些信号
  • 你需要一个集合点:stackoverflow.com/questions/7454524/…
  • CreateThread 返回线程创建后。它可能在创建的线程开始运行并初始化其数据结构之前返回。那么你究竟需要等待什么呢?
  • 直到线程能够接收到发送给它的消息
  • @popgalop:如果您使用正确的队列结构,那么您甚至可以在启动线程之前将消息排入队列。

标签: c++ multithreading winapi


【解决方案1】:

使用CreateEvent 创建一个事件句柄,您可以在该句柄上等待线程 A。您在线程 B 中做的第一件事就是发出该事件的信号。

struct thread_data {
    /* ... */
    HANDLE started_event;
};

线程 A:

/* We can create this on the stack. We wait for thread_B to
 * copy it into its own stack before signalling the event. */
struct thread_data td;

td.started_event = CreateEvent(
    NULL  /* security attributes */,
    FALSE /* manual reset (=NO) */,
    FALSE /* initially signalled (=NO) */,
    NULL  /* name (=none) */ );

CreateThread(NULL, 0, thread_B, &td, 0, NULL);
WaitForSingleObject(td.started_event, INFINITE);
CloseHandle(td.started_event);

线程 B:

DWORD WINAPI thread_B(LPVOID data)
{
    /* local copy of thread data */
    thread_data td = *((thread_data*)data);
    SetEvent(td.started_event);

    /* ... */
}

【讨论】:

  • 当您使用 C++ 时,我建议使用 ATL 的 CEvent 类:msdn.microsoft.com/en-us/library/efk30beh.aspx
  • @AcidJunkie:CEvent 只是使用 CreateEvent 创建的事件的包装器。使用该类没有任何好处,除了增加了一些(诚然很少)开销。
  • 特别是因为CEvent 是 ATL 的一部分,而 ATL 意味着 ActiveX/COM,应用程序可能根本没有使用它。
  • @Voo:当然,特殊情况是(出于某种原因)您必须能够应对内存不足的情况。那just came up recently in another question。既然您对这种情况有过实际经验,您可能想参与一下吗?
  • @Voo:线程池不能使用 _beginthread,因为并非所有使用它的应用程序都链接到 C 运行时。
【解决方案2】:

您的情况是您有两个线程,在它们之间发送消息。父线程需要发送消息,而子线程需要进行初始化才能接收。这会产生时间依赖性。

一种选择是使用事件让子进程向父进程发出信号,表明它已完成初始化并准备好接收消息。父级创建事件,将其传递给线程,然后等待事件。线程执行其初始化,然后发出事件信号。

这种方法效果很好,但对我来说它似乎不必要地复杂。为什么要启动一个线程然后阻塞直到它执行完工作?对我来说,这违背了线程的目的。

因此,替代方法是避免这种阻塞。由于在执行消息队列结构的初始化之前父线程无法继续,所以让我们将该初始化移至父线程。那么就不需要事件,也不需要阻塞。

  1. 在父线程中初始化消息队列结构。
  2. 创建子线程传递消息队列结构。
  3. 排队消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-16
    • 2017-01-02
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多