由于WPF中的锁定而避免UI阻塞

时间:2017-02-07 09:45:26

标签: c# wpf multithreading mvvm locking

我有以下问题。我有软件可以访问通过USB连接的硬件。

在UI中有一些按钮(比如搜索设备等)。

您可以启动一项锁定资源(USB设备)的任务,并在后台线程上执行耗时的操作。

问题是: 如果在需要此资源的GUI中按下按钮,则整个UI将被阻止,直到耗时的后台线程完成(由于锁定)。

我有一些想法如何解决这个问题,但似乎都有很多缺点。

到目前为止我的想法:

  • 使用Monitor.TryEnter检查是否可以访问资源。 ##缺点是这需要我更改所有ICommand实现(添加if语句)

  • 创建另一个ICommand实现,它具有锁定作为附加参数,并且只有在此锁定空闲时才执行该方法(我希望将其作为预定义的CanExecute语句)。 ##问题是,我不确定CanExecute的更改是否会正确填充(我可以创建一个后台任务,定期检查资源是否空闲,但我认为这可能会导致竞争条件......)< / p>

我正在寻找如何解决这个问题的想法,如果这不是一个建设性的问题&#34;请随意标记。

问候。

2 个答案:

答案 0 :(得分:1)

Execute()内,您可以使用Interlocked.CompareExchange()在产生工作人员之前设置忙标志。

稍后在您的CanExecute()中,只需执行Interlocked.Read()即可测试“忙碌”。

当您的工作人员完成时,只需通过执行另一个Interlocked.Exchange()来清除您的忙碌标志。

Interlocked类是线程安全的;相当快;并且上述模式不会阻止您的UI。

答案 1 :(得分:0)

您可以在关键部分周围使用异步锁定。 .NET Framework提供了具有异步SemaphoreSlim方法的WaitAsync类:

System.Threading.SemaphoreSlim _lock = new System.Threading.SemaphoreSlim(1, 1);

//Asynchronously wait to enter the semaphore... 
await _lock.WaitAsync();
try
{
    //do your thing in the critical section
}
finally
{
    _lock.Release();
}

还有AsyncLock类型,它是您可能使用的Stephen Cleary的AsyncEx库中可用的几乎等效的锁定关键字版本:https://github.com/StephenCleary/AsyncEx/wiki/AsyncLock

使用异步锁定,您可以等待释放锁定而不会阻止UI线程。