【问题标题】:wait for unknown number of threads created by CreateThread等待 CreateThread 创建的未知数量的线程
【发布时间】:2014-01-16 02:20:19
【问题描述】:

我需要创建未知数量的线程,最后希望等待所有创建的线程完成它们的工作。搜索后,我只能使用WaitForMultipleObjects(. . .) 等待一些已知数量的已创建线程,它需要指向已创建线程句柄数组的指针。以下代码是该场景的示例。

#include "stdafx.h"
#include <Windows.h>
#include <time.h>

FILE* fp;
time_t start;

struct mydata{
    int a, b;
};

void myFn(mydata* p)
{
    fprintf(fp, "a = %d\n", p->a);
    fprintf(fp, "b = %d\n", p->b);
    delete p;
}

bool condition()
{
     if(time(0) - start >= 1)
        return false;
     return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
    start = time(0);
    fopen_s(&fp, "outOfExe.txt", "w");
    mydata* dataToGive;
    int n = 0;
    while(condition())
    {
        n++;
        dataToGive = new mydata;
        dataToGive->a = 2*n;
        dataToGive->b = 4*n;
        HANDLE WINAPI handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myFn, dataToGive, 0, NULL);
    }
}

我能想到的解决方案是创建一个大小等于 CPU 内核数的数组,并在任何给定时间以该线程数的最大值执行。但是为此我需要开发一种排队机制等。有没有办法通过上面示例中所示的方式等待所有创建的线程?

【问题讨论】:

  • 有什么理由不能使用数组(或 std::vector)来存储句柄?还有为什么不使用 std::thread?
  • 我已将其作为解决方案之一编写 - 但想知道是否可以在不使用数组的情况下完成。 Visual c++ 2008 不支持 std::thread(对吗?)

标签: c++ windows multithreading visual-c++ visual-studio-2008


【解决方案1】:

使用std::vector 绝对是一种方法,并且不需要队列或具有可以存储的预设数量的线程句柄。下面的代码将创建所有线程,然后等待所有线程完成。

std::vector<HANDLE> threadHandles;
while(condition())
{
    n++;
    dataToGive = new mydata;
    dataToGive->a = 2*n;
    dataToGive->b = 4*n;
    HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myFn, dataToGive, 0, NULL);
    if(handle != INVALID_HANDLE_VALUE)
    {
        threadHandles.push_back(handle);
    }
}

::WaitForMultipleObjects(threadHandles.size(), &threadHandles[0], TRUE, INFINITE);

正如Martin WaitForMultipleObjects 所指出的,它可以等待的句柄数限制为 64 个。如果您需要超过 64 个线程,这将不起作用。

【讨论】:

  • WFMO 有 64 个句柄限制 :(
  • 如果我使用向量(或数组),出于效率原因,我不应该保持线程数等于内核数吗?
  • @MartinJames 确认!你是对的。我已经更新了我的答案来解决这个问题。
  • @BitManipulator 如果线程一直在执行(即不处于等待状态),那么是的,您可能会重新考虑同时启动这么多线程。
  • @BitManipulator - 在你的情况下,线程很可能在你开始等待之前完成 - 他们正在做 SFA :) 在一般情况下,线程做一些有用的事情,这一切都取决于你是否在线程中进行任何阻塞调用以及每个使用多少 L1 缓存。
【解决方案2】:

int threadCount、临界区、事件和WaitForSingleObject?

锁定 CS,创建线程,触发 threadCount,然后解锁 CS 并等待事件。

在线程函数/方法中,做你的事情,最后,锁定 CS,dec 线程计数。如果为 0,则发出事件信号。解锁CS并退出线程。

没有数组,没有向量,没有,(理智),线程数限制。

【讨论】:

  • 想解释一下“WaitForSingleObject?”我的理解是拥有一个全局线程数并增加/减少它获取锁定。在主线程结束时循环直到计数变为 0。
  • @BitManipulator 在开始时使用 CreateEvent。当一个线程看到这是最后一个时,它会使用 SetEvent 向 Event 发出信号。主线程使用 WaitForSingleObject 等待要发出的事件。
  • @BitManipulator - manuell 说的。循环是对 CPU 和内存带宽的浪费 - 等待事件不使用。
猜你喜欢
  • 1970-01-01
  • 2015-09-03
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多