我有一个程序,有时运行速度非常慢。
我试过Teleriks Justtrace找出,可能导致应用程序挂起的原因。
非UI线程(因此我认为它不是挂起的原因)确实是同步。获取对象(排队工作项)并将其除去以进行一些工作。
入队:
public void EnqueueObject(WorkUnit workunit)
{
try
{
workUnits.Add(workunit);
}
catch (Exception ex)
{
/handle exception
}
}
出列:
public WorkUnit Dequeue()
{
try
{
WorkUnit aWorkUnit = null;
workUnits.TryTake(out aWorkUnit, 1000);
return aWorkUnit ;
}
catch (InvalidOperationException ex)
{
//
}
return null;
}
TryTake用于检查当前工作的中止(而不是在调用时抛出一些错误的BlockingCollection Complete方法 - 我不想在程序流程中使用错误)
要求出队:
while(!isStopped)
{
ProcessWorkItem(Dequeue());
}
到目前为止看起来很简单。
问题是,Teleriks JustTrace显示,行“workUnits.TryTake(out aWorkUnit,1000);”占用程序总执行时间的30%。
这怎么可能?
有更多细节,它显示TryTake System.Threading.Monitor.Wait内部一直占用 - 我认为Wait会发送一个线程进入休眠状态,因此在等待期间它不会消耗掉一些东西。想法中的错误在哪里?
答案 0 :(得分:0)
您可以尝试使用workUnits.TryTake(out aWorkUnit)
而不使用timeout参数。然后,您应该修改while
循环以使其类似于:
while(!isStopped)
{
WorkUnit wu = Dequeue();
if(wu != null)
ProcessWorkItem(wu);
else
Thread.Sleep(40);
}
此外,如果您在UI线程上运行此代码,它将使您的UI无响应。您应该使用例如BackgroundWorker
进行操作。以下是MSDN文档中BackgroundWorker
类的描述:
BackgroundWorker类允许您在单独的专用线程上运行操作。下载和数据库事务等耗时的操作可能会导致用户界面(UI)在运行时停止响应。当您需要响应式UI并且您遇到与此类操作相关的长时间延迟时,BackgroundWorker类提供了一种方便的解决方案。