如何退出ThreadState.WaitSleepJoin C#?
这是我的密码:如何退出ThreadState.WaitSleepJoin C#?,c#,multithreading,C#,Multithreading,这是我的密码: protected AutoResetEvent _waitHandle = new AutoResetEvent(false); protected virtual void ThreadProc() { while (WorkState != WorkStates.Paused) { while (HasWork()) { if (WorkState == WorkStates.Paused || !D
protected AutoResetEvent _waitHandle = new AutoResetEvent(false);
protected virtual void ThreadProc()
{
while (WorkState != WorkStates.Paused)
{
while (HasWork())
{
if (WorkState == WorkStates.Paused || !DoWork())
break;
}
_waitHandle.WaitOne();
}
}
所以,当线程启动时,它检查是否有作业要做,完成后,它将等待设置_waitHandle。这里是wake函数,当新任务进入时调用它
public void Wake()
{
if ((_thread.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
_thread.Start();
else if (_thread.IsAlive)
_waitHandle.Set();
}
其中CreateThread如下所示:
protected virtual void CreateThread(bool start = false)
{
_thread = new Thread(ThreadProc) { IsBackground = true };
_thread.Name = GetType().Name;
if (start)
_thread.Start();
}
这段代码在大多数情况下都可以正常工作,但有时却不行。通常,当线程正在等待_waitHandle时,该线程处于活动状态,其状态更改为WaitSleepJoin。在本例中,调用_waitHandle.set()将使其再次激活。但是,有时它不工作,尽管状态相同(即线程处于活动状态,线程状态为WaitSleepJoin)
它似乎没有在_waitHandle.WaitOne()处等待,因为调用_waitHandle.set()不会触发。使线程再次循环的唯一方法是调用CreateThread(true)。问题是如何知道线程是否正在等待_waitHandle
下面是我在尝试处理这个问题时所做的一些研究,但是CreateThread()被调用的次数太多了
public void Wake()
{
if ((_thread.ThreadState & ThreadState.Unstarted) == ThreadState.Unstarted)
_thread.Start();
else if ((_thread.ThreadState & ThreadState.WaitSleepJoin) == ThreadState.WaitSleepJoin)
{
if (!_waitHandle.WaitOne(0))
_waitHandle.Set();
else
CreateThread(true);
}
else if (_thread.IsAlive)
_waitHandle.Set();
}
我不明白的是,如果_thread.IsAlive为true,且其线程状态为WaitSleepJoin,那么线程在哪里(我确保线程中也没有活动工作)?如何唤醒它?出于好奇,不使用TPL的原因是什么?在唤醒方法(问题的最后一个代码段)中,为什么要创建更多线程对象并启动它们并将它们分配给_thread字段?这样做的目的是什么?它看起来非常错误…很可能在原始代码中创建了两个或多个运行ThreadProc方法的线程。这意味着,您还有两个或多个线程在等待_waitHandle。记住,waitHandle是一个自动resetEvent。如果发出自动重置事件的信号,则只会唤醒一个线程,然后自动重置自动重置事件(因此而得名)。在此AutoResetEvent上等待的任何其他线程都将继续等待。也许当你认为设置waitHandle并没有唤醒你的线程时,它只是唤醒了另一个线程,而不是你所看到的那个线程……关于为什么不使用TPL的问题,这来自于遗留代码和我的遗留思想,但如果有人能帮我将此代码翻译成TPL,我愿意切换。@elgonzo,正如我在问题中所说的,在WaitSleepJoin状态下添加CreateThread是在它卡住时重新启动它的唯一方法。这实际上是我问这个问题的主要原因。