我正在用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);
}
调用函数,用作运行函数的包装:
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解决方案。
好,坏消息是您无法重新启动线程。即,线程退出后,它将永远消失并且无法重新启动。
好消息是,您可以做一些事情来有效地实现所需的行为,无论如何:
1]调用WaitForSingleObject(m_handle, INFINITE);
和CloseHandle(m_handle);
清理旧的/退出的线程,然后以与启动原始线程相同的方式启动新线程(即,调用_beginthreadex()
和ResumeThread()
,依此类推)。该逻辑都可以封装在您的Thread
类中,以便就任何调用代码而言,该线程似乎都在“重新启动”(如果重要,则使用不同的线程ID)。
或者,或者(如果您不想每次都启动新线程的开销):
2)永远不要让线程退出。也就是说,让您的线程入口函数执行以下操作(伪代码):
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;
}
然后,只要您的主线程想要“重新启动”内部线程,它将在Thread对象的条件变量上调用WakeConditionVariable,以将内部线程从运行后睡眠中唤醒,然后内部线程将调用[ C0]。 (并且,如果要退出内部线程,除了将Run()
设置为true以外,您将执行相同的操作-并不是timeToQuit
应该是timeToQuit
或类似名称,才能保证线程安全)) >