在我的应用程序中,我正在执行大量文件的删除,当我单击“删除”按钮时,我的应用程序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”。
然后应用程序进入挂起模式。
我单击全部破坏(Ctrl + Alt + Break)。
当从VS中按下Break All时,它停留在Monitor.Wait(this, waitTime);
,它开始等待完成,并且我无法执行任何其他UI操作。
我正在阅读MSDN文章,其中有一些使用Monitor类管理线程的示例,但我认为我缺少一些内容。
有什么方法可以使用户界面不受此后台删除操作的影响?
我希望在后台执行此删除操作时执行其他UI操作。
非常感谢您的帮助,谢谢。
这里有一些对我有用的方法:结合使用CancellationToken和SemaphoreSlim互斥对象以保持线程安全,这样我们就不必在运行时阻止UI线程。
CancellationTokenSource _cts = null; SemaphoreSlim ssBusy = new SemaphoreSlim(2); private void DeleteManyFiles() { try { ssBusy.Wait(); switch (ssBusy.CurrentCount) { case 1: _cts = new CancellationTokenSource(); for (int i = 0; i < NUMBER_OF_FILES_TO_DELETE; i++) { bool cancelled = DeleteSingleFile(_cts.Token); } break; case 0: // A count of 0 indicates that the operation is already in progress. MessageBox.Show("Deletion is already in progress"); break; default: break; } } catch(Exception ex) { Debug.Assert(false, ex.Message); } finally { ssBusy.Release(); } }
......
private bool DeleteSingleFile(CancellationToken ct) { if(ct.IsCancellationRequested) { return true; } // Simulate half a second to delete one file Task.Delay(500).Wait(); // SIMULATE ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // Decrement remaining count _remaining--; // Notify the UI thread FileDeleted?.Invoke(this, EventArgs.Empty); return false; } event EventHandler FileDeleted;
我将完整的工作示例发布在我们的GitHub上。您可以浏览或单击Clone or Download,如果这对您有帮助。