我想重新 运行 一个线程

I want to re run a Thread

我正在用 C++ 实现 Java 风格的线程。为了做到这一点,我有一个 Thread::Start 函数,但我的问题是,当我使用它时,由于某种原因,它只在第一次工作正常,一旦线程实例调用开始它完成但我不能调用开始再次调用其他线程的启动函数。

这是我的线程构造函数:

Thread::Thread()
{
    m_handle = (HANDLE)_beginthreadex(0, 0, &call, this, CREATE_SUSPENDED, 0);
}

线程析构函数:

Thread::~Thread()
{
    if (m_handle) CloseHandle(m_handle);
}

调用它用作 运行 函数包装器的函数:

unsigned int __stdcall Thread::call(void* _this)
{
    ((Thread*)_this)->Run();
    return 0;
}

这是我的开始功能:

void Thread::Start()
{
    if (m_handle) ResumeThread(m_handle);
}

有问题的代码如下:

店员class:

struct Clerk : public Thread
{
    Clerk()
    {
        IsOnService = false;
    }
    void Run()
    {
        std::cout << this->GetId() << " receive new customer " << '\n';
        Sleep(2000);
        std::cout << this->GetId() << " has finished" << '\n';
        IsOnService = false;
    }

    bool IsOnService;
};

服务class:

struct Service
{
    Clerk*      clerk;
    Customer*   customer;
    Service(Clerk* c, Customer* cu)
    {
        clerk = c;
        customer = cu;
        clerk->Start();
    }
    ~Service()
    {
        delete customer;
    }
};

主要功能:

int main()
{
    int nClerks = 5;
    Clerk* clerks[] = { 
        new Clerk(), new Clerk(), new Clerk(), new Clerk(), new Clerk()
    };
    Queue<Customer*> awaitingCustomers;
    while (1) 
    {
        if (GetAsyncKeyState(0x43) & 0x7FFF) 
        {
            Customer* newCustomer = new Customer();
            awaitingCustomers.Push(newCustomer);
            while (!awaitingCustomers.IsEmpty())
            {
                for (int i = 0; i < nClerks; ++i)
                {
                    if (!clerks[i]->IsOnService)
                    {
                        Service* newService = new Service(clerks[i], awaitingCustomers.Pop());
                        delete newService;
                        break;
                    }
                }
            }
        }
    }
    for (int i = 0; i < nClerks; ++i) delete clerks[i];
    return 0;
}

当我 运行 上面的代码只调用一次 Start 函数而不是每次都调用它,因为我按下 'c' 键。 我需要一个 c++98 解决方案,谢谢。

好吧,坏消息是您无法重新启动线程。即一旦线程退出,它就永远消失了,无法重新启动。

好消息是,无论如何,您可以做一些事情来有效地实现您想要的行为:

1) 调用 WaitForSingleObject(m_handle, INFINITE);CloseHandle(m_handle); 清理 old/exited 线程,然后像启动原始线程一样启动一个新线程(即调用 _beginthreadex()ResumeThread() 等等)。这个逻辑都可以封装在你的 Thread class 中,这样就任何调用代码而言,线程似乎是 "restarted" (尽管有不同的线程 ID,如果这很重要).

或者,或者(如果您不想每次都启动新线程的开销):

2) 从一开始就不要让你的线程退出。也就是说,让你的 thready-entry 函数做这样的事情(伪代码):

unsigned int __stdcall Thread::call(void* _this)
{
   while(timeToQuit == false)
   {
      // Do the normal Thread thing
      ((Thread*)_this)->Run();

      EnterCriticalSection(...);
      // we'll block here until the main thread wakes us up 
      SleepConditionVariableCS(...);
      LeaveCriticalSection(...);
   }
   return 0;
}

然后,每当您的主线程想要 "restart" 内部线程时,它会调用 Thread 对象的条件变量 WakeConditionVariable 以将内部线程从其 post- 中唤醒运行 睡眠,然后内部线程会再次调用 Run()。 (如果你想退出内部线程,除了先将 timeToQuit 设置为 true 之外,你会做同样的事情 - 而不是 timeToQuit 应该是 std::atomic<bool> 或类似的,以便是线程安全的)