【发布时间】:2020-06-07 12:10:42
【问题描述】:
在我的应用程序中,我正在删除大量文件,当我单击删除按钮时,我的应用程序 UI 将被挂起,直到删除完成。
这是导致挂起的方法。
/// <summary>
/// Attempts to acquire the CountDown, timing out after a specified
/// interval.
/// </summary>
/// <param name="timeout">The maximum time to wait.</param>
/// <returns>
/// Boolean true if the CountDown was acquired. Boolean false if the
/// method timed out.
/// </returns>
public bool Attempt(TimeSpan timeout)
{
lock (this)
{
if (_count <= 0) return true;
if (timeout <= TimeSpan.Zero) return false;
TimeSpan waitTime = timeout;
DateTime start = DateTime.Now;
for (; ; )
{
// if the thread has been interrupted, Wait() will throw
// ThreadInterruptedException()
Monitor.Wait(this, waitTime);
if (_count <= 0) return true;
waitTime = timeout - (DateTime.Now - start);
if (waitTime <= TimeSpan.Zero) return false;
}
}
}
我执行的步骤:
单击了应用程序窗口窗体中的按钮“btnDel”。
然后应用程序进入挂起模式。
我点击了Break All(Ctrl+Alt+Break)。
当从 VS 按 Break All 时,它卡在 Monitor.Wait(this, waitTime); 并开始等待完成,我无法执行任何其他 UI 操作。
我正在阅读 MSDN 文章,其中有一些使用 Monitor 类管理线程的示例,但我认为我遗漏了一些东西。
有什么方法可以让 UI 摆脱这个后台删除操作?
当此删除在后台处于活动状态时,我想执行其他 UI 操作。
任何帮助将不胜感激,谢谢。
【问题讨论】:
-
请分享minimal reproducible example。还要清楚这是 WPF 还是 Winforms。
-
我建议将要删除的文件列表填充到
BlockingCollection中,然后从新的Task处理该阻塞集合。 -
我无法理解您问题的标题或正文如何以任何方式映射到您显示的代码。目前尚不清楚
CountDown是什么,以及为什么您觉得需要获取它。我也不清楚你想通过Wait调用来实现什么。 -
附带说明,如果调用
Monitor.Wait(this, waitTime)发生并且waitTime是否定的,则调用可能会失败并返回ArgumentOutOfRangeException。如果在应用程序执行期间系统时钟向后移动,则可能会发生这种情况。因此,不建议使用属性DateTime.Now来测量间隔。Stopwatch类更适合此目的。
标签: c# multithreading monitor ui-thread background-thread