为什么线程进入WaitSleepJoin状态?

时间:2014-03-05 16:02:44

标签: c# multithreading

我正在编写运行后台线程的单例类。以下是它的开始和维护方式:

 private void EnsureBackgroundThread()
        {
            try
            {
                if (this.RunnerThread == null)
                    this.RunnerThread = new Thread(this.BackgroundRunner) { IsBackground = true };

                if (this.RunnerThread.ThreadState != ThreadState.Running)
                {
                    Debug.WriteLine("----ApplePushNotificatorService.EnsureBackgroundThread ThreadState: " + this.RunnerThread.ThreadState);
                    this.RunnerThread.Start();
                }
            }
            catch (Exception ex)
            {
                this.LoggerService.Log(null, ex);
            }
        }

我在TestClass这个类中调用我的方法,如下所示:

apns.Send("dev", devices, "Testing...", out badIds);

            // Wait 5 seconds to let it send stuff through.
            Thread.Sleep(5000);

            devices.Clear();
            devices.Add("some bad id");

            // Now let's call this again, but this time we should get back some bad Ids
            apns.Send("dev", devices, "Testing...", out badIds);

            // Wait 5 seconds to let it send stuff through.
            Thread.Sleep(5000);

            devices.Clear();
            devices.Add("9edc21d0d4e369f50040c5d2c94f2ea29c7d596090e4ddae253712cd406391df");
            apns.Send("dev", devices, "Test message for Andrew's phone", out badIds);

            // Wait 5 seconds to let it send stuff through.
            Thread.Sleep(5000);

我查看了错误日志,并看到了异常:

  

线程正在运行或终止;它无法重启。

在调试中它说:

  

---- ApplePushNotificatorService.EnsureBackgroundThread ThreadState:Background,WaitSleepJoin

为什么进入“WaitSleepJoin”状态?是因为我在测试中做了“Thread.Sleep”吗?

保持线程活着的代码看起来是否正确?我该如何解决这个问题?这个想法是在单例调用“发送”方法时 - 我们需要确保后台线程正在运行。

编辑:

这是重新正常工作的代码

private void EnsureBackgroundThread()
        {
            try
            {
                if (this.RunnerThread != null && this.RunnerThread.IsAlive) return;
                this.RunnerThread = new Thread(this.BackgroundRunner) { IsBackground = true };
                this.RunnerThread.Start();
            }
            catch (Exception ex)
            {
                this.LoggerService.Log(null, ex);
            }
        }

2 个答案:

答案 0 :(得分:4)

状态告诉我们线程当前正在休眠,可能是在您对Sleep的一次调用中。这意味着它仍在运行。因为它仍在运行,所以无法启动它。你试图多次启动同一个线程。你不能这样做。你启动它一次,然后它就开始了,就是这样。尝试在第二次启动它时,无论是在运行时还是在完成之后,都是不可能的。

答案 1 :(得分:2)

很简单,因为错误声明:您的线程已经创建并且正在运行或终止 - 然后您尝试再次启动它。

大概在你的TestClass你有多次打电话给你的单身人士课(我猜这可能是在apns.Send电话下的某个地方)。第一次调用EnsureBackgroundThread时,将创建并启动单个线程。下次您致电EnsureBackgroundThread时,会在同一线程上拨打Thread.Start ,从而导致同样的错误。

这里可能需要注意的是,当一个线程完成时,引用它的变量不会设置为null - 但更有可能你只是多次调用EnsureBackgroundThread方法而且你写的代码不支持。