获取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线程上的锁

如果它可以正常工作,我就不会更改它。

如果您有性能问题,那么您可以调整它。需要改进的地方:

主要
    任何可能长时间运行的操作都应该在非ui线程中执行。这意味着您需要从类中删除RefreshInForeground,并使用Task, ThreadPool, BackgroundWorker等从UI运行RefreshInBackground

  • 切换到Monitortry-finally,添加timeout。这仍然不是最好的选择,因为UI线程最多阻塞timeout的持续时间。总比永远等待好。
  • 使用优化的储物柜,如ReaderWriterLockSlim
  • 使用ConcurrentDictionary -无锁或非阻塞类

当RefreshInForegound被UI线程调用时,它必须等待锁(也许),问题是,这是一个不好的做法,如果是为什么?

如果操作可能需要很长时间,这可能是一个问题,因为它阻塞了UI。

如果使用相同锁对象的所有操作都很短(例如您示例中的简单字典设置器),我不会担心它。

对于字典,自。net 4.0以来有ConcurrentDictionary类。看到

字典作为线程安全变量

对于其他类型的线程安全集合,您可以看到http://msdn.microsoft.com/en-us/library/dd287108.aspx

对于锁定问题,这是一个不错的做法。在日常使用中,lock关键字是管理并发性最方便的方法,但不是最优的方法。例如,如果您正在进行单写多读同步,则ReaderWriterLock可能更好。