我的测试应用程序出了问题。我正在运行一个win表单应用程序,可以将请求发布到Web服务。有一个定时器,它定期将项添加到请求队列中。我有一个名为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);
}
}
答案 0 :(得分:2)
您使用m_processorQueue的锁无效。你将局部变量thisObject锁定,但这意味着每个线程都有自己的锁对象,它们永远不会等待......
声明thisObject
,使其与m_processorQueue
具有相同的范围和生命周期。
但是我也注意到你的bgw做了一个繁忙的循环,它将消耗大量的CPU时间。您需要一些机制来等待空队列。
如果您使用的是Fx4,请使用ConcurrentQueue。否则寻找一个良好的队列实现。
答案 1 :(得分:0)
将锁定(thisObject)从local移动到方法,从global移动到type。
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
。