获取UI线程上的锁
本文关键字:线程 UI 获取 | 更新日期: 2023-09-27 18:11:34
在UI线程上获得锁是一种不好的做法吗?例如,我有一个缓存对象,它正在被后台线程和UI线程修改。对缓存的任何修改都封装在锁中。伪代码如下:
public class Cache
{
private readonly Dictionary<string, IEnumerable<string>> _cache;
private readonly object _onCache = new object();
public Cache()
{
_cache = new Dictionary<string, IEnumerable<string>>();
}
//Called by worker threads
public void RefreshInBackground(IEnumerable<string> items, string key)
{
lock (_onCache)
{
_cache[key] = items;
}
}
//Called by UI thread.Does this lead to any issues since UI thread is waiting on a lock?
public void RefreshInForeground(IEnumerable<string> items, string key)
{
lock (_onCache)
{
_cache[key] = items;
}
}
}
当RefreshInForegound被UI线程调用时,它必须等待锁(也许),问题是,这是一个不好的做法,如果是为什么?
谢谢,迈克
如果它可以正常工作,我就不会更改它。
如果您有性能问题,那么您可以调整它。需要改进的地方:
主要- 任何可能长时间运行的操作都应该在非ui线程中执行。这意味着您需要从类中删除
RefreshInForeground
,并使用Task
, ThreadPool
, BackgroundWorker
等从UI运行RefreshInBackground
。- 切换到
Monitor
和try-finally
,添加timeout
。这仍然不是最好的选择,因为UI线程最多阻塞timeout
的持续时间。总比永远等待好。 - 使用优化的储物柜,如
ReaderWriterLockSlim
- 使用
ConcurrentDictionary
-无锁或非阻塞类
当RefreshInForegound被UI线程调用时,它必须等待锁(也许),问题是,这是一个不好的做法,如果是为什么?
如果操作可能需要很长时间,这可能是一个问题,因为它阻塞了UI。
如果使用相同锁对象的所有操作都很短(例如您示例中的简单字典设置器),我不会担心它。
对于字典,自。net 4.0以来有ConcurrentDictionary
类。看到
字典作为线程安全变量
对于其他类型的线程安全集合,您可以看到http://msdn.microsoft.com/en-us/library/dd287108.aspx
对于锁定问题,这是一个不错的做法。在日常使用中,lock
关键字是管理并发性最方便的方法,但不是最优的方法。例如,如果您正在进行单写多读同步,则ReaderWriterLock
可能更好。