我正在用C ++实现Java样式线程。为了做到这一点,我有一个Thread :: Start函数,但是我的问题是,当我使用它时,由于某种原因,一旦线程实例调用开始运行它就完成了,但是它只能在第一次正常运行,但是我不能再次调用start并且都不调用其他线程的启动函数。
这是我的线程构造函数:
Thread::Thread()
{
m_handle = (HANDLE)_beginthreadex(0, 0, &call, this, CREATE_SUSPENDED, 0);
}
线程析构函数:
Thread::~Thread()
{
if (m_handle) CloseHandle(m_handle);
}
调用函数,用作Run函数的包装器
unsigned int __stdcall Thread::call(void* _this)
{
((Thread*)_this)->Run();
return 0;
}
这是我的启动功能:
void Thread::Start()
{
if (m_handle) ResumeThread(m_handle);
}
出现问题的代码如下:
店员班:
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;
};
服务类别:
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解决方案。
答案 0 :(得分:1)
好吧,坏消息是您无法重新启动线程。即,线程退出后,它将永远消失并且无法重新启动。
好消息是,无论如何,您可以做一些事情来有效地实现所需的行为:
1)调用WaitForSingleObject(m_handle, INFINITE);
和CloseHandle(m_handle);
清理旧的/退出的线程,然后以与启动原始线程相同的方式启动新线程(即,调用_beginthreadex()
和{ {1}},依此类推。此逻辑都可以封装在ResumeThread()
类中,以便就任何调用代码而言,该线程似乎都在“重新启动”(如果有关系,则使用不同的线程ID)。
或者,或者(如果您不想每次都启动新线程的开销):
2)切勿首先退出线程。也就是说,让您的线程入口函数执行以下操作(伪代码):
Thread
然后,只要您的主线程想要“重新启动”内部线程,它将在Thread对象的条件变量上调用WakeConditionVariable,以将内部线程从运行后睡眠中唤醒,然后将内部线程唤醒会再次调用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;
}
。 (并且,如果要退出内部线程,除了将Run()
设置为true之外,您将做同样的事情-并非timeToQuit
应该是timeToQuit
或类似的名称,以便是线程安全的)