我有以下问题。我有软件可以访问通过USB连接的硬件。
在UI中有一些按钮(比如搜索设备等)。
您可以启动一项锁定资源(USB设备)的任务,并在后台线程上执行耗时的操作。
问题是: 如果在需要此资源的GUI中按下按钮,则整个UI将被阻止,直到耗时的后台线程完成(由于锁定)。
我有一些想法如何解决这个问题,但似乎都有很多缺点。
到目前为止我的想法:
使用Monitor.TryEnter检查是否可以访问资源。 ##缺点是这需要我更改所有ICommand实现(添加if语句)
创建另一个ICommand实现,它具有锁定作为附加参数,并且只有在此锁定空闲时才执行该方法(我希望将其作为预定义的CanExecute语句)。 ##问题是,我不确定CanExecute的更改是否会正确填充(我可以创建一个后台任务,定期检查资源是否空闲,但我认为这可能会导致竞争条件......)< / p>
我正在寻找如何解决这个问题的想法,如果这不是一个建设性的问题&#34;请随意标记。
问候。
答案 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线程。