【问题标题】:Threads staying alive after execution执行后线程保持活动状态
【发布时间】:2012-07-30 15:11:13
【问题描述】:

我创建了一个处理ThreadsThreadManager 类,它的任务是添加新的threads 并清理死去的threads。但是,创建的 threads 保持 活动 并处于 ThreadState.WaitSleepJoin 状态。我已经检查过主体是否已成功完成执行。有什么想法吗?

    public bool TryAddThread(ThreadStart threadBody, ThreadStartInfo startInfo)
    {
        bool success = false;

        // Validate arguments
        if (threadBody == null || startInfo == null)
        {
            return false;
        }

        if (!Monitor.TryEnter(_lock) || !_allowNewThreads)
        {
            return false;
        }

        try
        {
            Thread newThread = new Thread(threadBody);

            StartThread(newThread, null, startInfo);

            success = true;
        }
        finally
        {
            Monitor.Exit(_lock);
        }

        return success;
    }

    private void StartThread(Thread newThread, object threadParams, ThreadStartInfo startInfo)
    {
        if (newThread == null || startInfo == null)
        {
            return;
        }

        // Apply start info
        newThread.Name = startInfo.Name;
        newThread.SetApartmentState(startInfo.ApartmentState);
        newThread.IsBackground = startInfo.IsBackground;

        if (threadParams == null)
        {
            newThread.Start();
        }
        else
        {
            newThread.Start(threadParams);
        }

        _threads.Add(newThread);

        RemoveDeadThreads();
    }

    public void RemoveDeadThreads()
    {
        _threads.RemoveAll(t => (!t.IsAlive));
    }

在主线程中执行:

    public void InsertAsync(AP p, APr pr)
    {
        ParameterizedThreadStart thread = new ParameterizedThreadStart(InsertPr);
        List<object> parameters = new List<object>();

        // Create new controller. Must be before the thread to avoid cross-thread operation exception.
        PageController controller = new PageController();
        controller.Initialize(siteWebBrowser);

        parameters.Add(controller);
        parameters.Add(p);
        parameters.Add(pr);
        parameters.Add(_session);

        // If the thread cannot start notify listeners
        if (!_threadManager.TryAddThread(thread, parameters, new ThreadStartInfo("InsertAsync", ApartmentState.STA, true)) && ThreadCreationFailed != null)
        {
            _logger.Error("InsertAsync: Could not start thread.");
            ThreadCreationFailed();
        }

    }

    private static void InsertPr(object o)
    {
        try
        {
            _logger.Debug("Thread start - InsertPr");

            List<object> parameters = (List<object>)o;
            PageController controller = (PageController)parameters[0];
            AP p = (AP)parameters[1];
            APr pr = (APr)parameters[2];
            Session session = (Session)parameters[3];

            if (patient == null)
            {
                throw new ArgumentException("Null patient.");
            }

            session.WaitForHistorySynchronizationSuspension();

            if (Program.ShouldAbortBackgroundOperations)
            {
                throw new Exception("Aborting..");
            }

            session.DoingSomeJob = true;



            controller.ClearCurrent();

            controller.GoToHomePage(3, true);

            controller.ClickNew();


            controller.SearchForP(p.Id);


            try
            {
                controller.WaitUntilDivExists(Constants.NewPrContainerDivId);
            }
            catch (Exception)
            {
                _logger.Error("InsertAsync: Error while waiting for div '" + Constants.NewPrContainerDivId + "' to appear.");
                throw;
            }

            if (PrInsertionCompleted != null)
            {
                PrInsertionCompleted();
            }
        }
        catch (Exception ex)
        {
            _logger.ErrorException("InsertAsync", ex);

            if (InsertionFailed != null)
            {
                InsertionFailed(Constants.MessageFailed);
            }
        }
    }

【问题讨论】:

  • 有几件事: 1) 为什么不使用线程池? 2) 线程状态取决于这些线程中发生了什么(这些委托中是否有任何睡眠或等待句柄?) 3) 如果_allowNewThreads 为假,您可能永远不会释放该锁(您你应该lock声明)
  • 如果没有执行线程代码,很难详细回答这个问题。
  • 我被指示不要使用ThreadPool 或任何其他线程管理方法。听起来很奇怪,但这是我的指示。
  • Threads 存储在列表中的目的是什么?
  • 您对以“Wait”开头的方法有两个调用,似乎其中之一是将线程置于等待状态。

标签: c# execution termination thread-state


【解决方案1】:

当程序的主启动线程终止时,您可以要求 CLR 自动中止线程。但这不是自动的,您必须将线程的 IsBackground 属性显式设置为 true。线程池线程会自动开启该属性。

【讨论】:

  • 这是目前发生的情况。应用程序自动关闭Threads,但我想知道为什么会这样?在实际启动Thread 之前释放锁是个好主意吗?
  • 我不明白你的意思。 启动线程时释放锁与您的程序终止有什么关系?当您的进程结束时,锁定状态根本不重要。
  • “关闭线程”没有任何意义,线程没有 Close() 方法,也没有 Dispose() 方法。因此很难知道你在说什么。使用此类线程的堆栈跟踪更好地记录您的问题。您的代码中的具体问题是 startInfo.IsBackground。这应该永远是真的。
  • 我在解码您的 cmets 时遇到了严重问题,“怎么可能”准确地执行 what?当你的程序终止时,你为什么要担心 ThreadState?您应该认真考虑放弃此代码并使用 ThreadPool。
  • Thread 类没有 Dispose() 方法。这意味着本机操作系统线程一直存在,直到垃圾收集器运行。 GC.Collect() 会这样做,但是在程序终止之前调用它是没有意义的。这是 ThreadPool 类知道如何处理的另一个问题。
【解决方案2】:

WaitSleepJoin 表示线程已通过调用 lock (Monitor.Enter)、调用 Thread.Sleep、调用 Thread.Join 或其他一些线程同步对象来阻塞自己。

也许如果您提供导致此线程状态的示例线程入口点,有人可以提供更详细的答案。

【讨论】:

  • 我可以向您保证,线程主体已完成执行。我已经调试过了,一切正常(不幸的是我无法提供详细的代码)。我看到最后一个} 正在执行,并且线程完成的工作也符合预期100%。锁也被释放,但线程仍处于睡眠/等待/加入状态。
  • 嗯,我很难相信系统在骗你……我发现系统更可能是正确的,而你的线程实际上被阻塞了。没有看到代码,我们无法真正分辨。
  • 如果我运行一个简单地退出的线程的快速示例,状态是 Stopped 而不是 WaitSleepJoin。
  • 我添加了一些额外的代码。退出的线程是Stopped。也是Alive吗?
  • @Souvlaki 不,一个线程不能是Stopped 并且有IsAlive true
猜你喜欢
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-19
相关资源
最近更新 更多