线程池队列在第10个项目上停止

本文关键字:项目 10个 队列 线程 | 更新日期: 2023-09-27 18:12:21

我的测试应用程序有问题。我正在运行一个可以发布请求到web服务的win form应用程序。有一个计时器,它定期向请求队列中添加项目。我有一个名为AutoManager的类,用于从队列中挑选项目并将它们发送到web服务。

在TryKickQueue()中,它将IAutoProcessor添加到线程池队列中。一旦IAutoProcessor完成,它会回调AutoManager从队列中移除自己。

这工作得很好,运行前10个请求没有问题,但由于某种原因,我无法弄清楚第10个线程从未完成,所以它卡住了。这很奇怪,因为它总是第10号。我做错了什么吗,我应该清理一下吗?

应该发生这种情况,或者它可能是一个死锁,我还没有能够找到?

多谢尼尔。

    public AutoManager(Settings _settings, Log _log)
    {
        m_sessionKicker = new BackgroundWorker();
        m_sessionKicker.DoWork += SessionKickerDoWork;
        m_sessionKicker.RunWorkerCompleted += SessionKickerRunCompleted;
        m_sessionKicker.WorkerSupportsCancellation = true;
        m_sessionKicker.RunWorkerAsync();
        m_processorQueue = new List<IAutoProcessor>();
        m_inProcessingQueue = new List<IAutoProcessor>();
    }
    private void SessionKickerDoWork(object sender, DoWorkEventArgs e)
    {
        bool bFinished = false;
        while (!bFinished)
        {
            TryKickQueue();
        }
    }
    private void TryKickQueue()
    {
        object thisObject = new Object();
        lock (thisObject)
        {
            if (m_processorQueue.Count > 0 && m_inProcessingQueue.Count < m_settings.MaxThreads)
            {
                IAutoProcessor proc = m_processorQueue[0];
                m_inProcessingQueue.Add(proc);
                m_processorQueue.RemoveAt(0);
                if (proc != null)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(proc.SendData));
                }
            }
        }
    }
    public void OnRemoveAutoProcessor(IAutoProcessor _autoProcessor)
    {
        object thisObject = new Object();
        lock (thisObject)
        {
            m_inProcessingQueue.Remove(_autoProcessor);
        }
    }

线程池队列在第10个项目上停止

您对m_processorQueue使用的锁定无效。你锁定了本地变量thisObject,但这意味着每个线程都有自己的锁定对象,它们永远不会等待…

声明thisObject,使其具有与m_processorQueue相同的作用域和生存期。

但是我也注意到你的bgw做一个忙循环,它将消耗大量的CPU时间。您需要某种机制来等待空队列。

如果你正在使用Fx4,那么使用ConcurrentQueue。否则,寻找一个好的队列实现。

将您的锁(thisObject)从本地移动到方法,从全局移动到类型。

    static object thisObject = new Object();
    private void TryKickQueue() 
    { 
        lock (thisObject) 
        { 
           // your logic
        } 
    } 
    public void OnRemoveAutoProcessor(IAutoProcessor _autoProcessor) 
    { 
        lock (thisObject) 
        { 
           //your logic
        } 
    }

不知道你为什么要检查这个m_inProcessingQueue.Count < m_settings.MaxThreads