1

我有一个有时运行速度很慢的程序。

我尝试了 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 会发送一个线程进入睡眠状态,因此它在等待期间不会消耗任何东西。思想的错误在哪里?

4

1 回答 1

0

您可以尝试workUnits.TryTake(out aWorkUnit)不使用 timeout 参数。然后,你应该修改while循环看起来类似于这样:

 while(!isStopped)
 {
    WorkUnit wu = Dequeue(); 
    if(wu != null) 
       ProcessWorkItem(wu);
    else
       Thread.Sleep(40);
 }

此外,如果您在 UI 线程上运行此代码,它会使您的 UI 无响应。例如,您应该使用BackgroundWorker该操作。这是BackgroundWorkerMSDN 文档中对类的描述:

BackgroundWorker 类允许您在单独的专用线程上运行操作。下载和数据库事务等耗时的操作可能会导致您的用户界面 (UI) 在运行时似乎停止响应。当您需要响应式 UI 并且面临与此类操作相关的长时间延迟时,BackgroundWorker 类提供了一种方便的解决方案。

于 2013-02-27T13:03:16.973 回答