可以请我解释一下为什么此代码不会导致死锁吗?

static Object listlock = new Object();

void StartAsync()
{
    System.Threading.Tasks.Task.Factory.StartNew(() =>
        {
            lock(listlock)
                base.OnPropertyChanged("MyList");
        });
}

 public ObservableCollection<MyObjects> MyList
 {
    get
    {
         lock(listlock)
             return  new ObservableCollection<MyObjects>(_myObjectList);
    }
 }

一些背景细节:
该程序使用的是 MVVM 模式,并且 MyList 已绑定(bind)到 WPF UI 上的 Datagrid 上。
_myObjects 只是对象的随机列表。
是否因为 OnPropertyChange 只是通知UI,它必须从MyList中获取新数据,而只是返回而不关心UI是否实际获取Data?我知道OnPropertyChanged是在单独的线程上调用的,但是UI在单个线程上存在(不是O.o),所以被通知的线程也是获取数据的线程。我会因为这个原因而无法释放锁?

最佳答案

此处的关键实现是PropertyChanged的处理程序确实调度了一些可访问UI线程上的MyList的代码,但并不等待它完成

因此,事件的一种可能的顺序是:

  • StartAsync()锁定后台线程。
  • 引发PropertyChanged
  • MyList
  • PropertyChanged的处理程序计划在UI线程上访问MyList的代码。
  • PropertyChanged的处理程序返回。
  • 锁已释放。
  • UI线程尝试访问MyList
  • UI线程无需等待就可以获取锁,因为没有其他线程拥有它。

  • 另一种表达方式:我认为您期望的是PropertyChanged的处理程序执行以下操作:
    Dispatcher.Invoke(() =>
    {
        if (e.PropertyName == "MyList")
        {
            var newList = model.MyList;
            // set newList as the current value of some binding
        }
    });
    

    但实际上,它的功能类似于(唯一的区别是第一行):
    Dispatcher.BeginInvoke(() =>
    {
        if (e.PropertyName == "MyList")
        {
            var newList = model.MyList;
            // set newList as the current value of some binding
        }
    });
    

    关于c# - 为什么代码不会死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15650778/

    10-17 02:34