尝试在blockingcollection上取性能
本文关键字:性能 blockingcollection | 更新日期: 2023-09-27 18:01:17
我有一个程序有时运行得很慢。
我尝试了Teleriks Justtrace来找出可能导致应用程序挂起的原因。
一个非UI线程(因此我相信它不是真正的挂起的原因)做assync。获取对象(Enqueues工作项)并请求它做一些工作。
排队:
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会将一个线程发送到睡眠状态,所以它在等待期间不会消耗任何东西。这个想法的错误在哪里?
您可以尝试使用不带timeout参数的workUnits.TryTake(out aWorkUnit)
。然后,您应该将while
循环修改为如下所示:
while(!isStopped)
{
WorkUnit wu = Dequeue();
if(wu != null)
ProcessWorkItem(wu);
else
Thread.Sleep(40);
}
同样,如果你在一个UI线程上运行这段代码,它将使你的UI无响应。例如,您应该使用BackgroundWorker
进行操作。以下是MSDN文档中BackgroundWorker
类的描述:
BackgroundWorker类允许你在一个单独的专用线程上运行一个操作。下载和数据库事务等耗时的操作可能会导致用户界面(UI)在运行时看起来好像停止了响应。当你想要一个响应的UI,并且你面临着与这些操作相关的长时间延迟时,BackgroundWorker类提供了一个方便的解决方案。