我有两节课
public class ConccClass<T> : ObservableCollection<T>
{
}
Run Code Online (Sandbox Code Playgroud)
和
public class TestTherad: INotifyPropertyChanged
{
private string name;
public string Name
{ get {
return name;
}
set
{
if (value != name)
{
name = value;
RaisePropertyChanged("Name");
}
}
}
//// the notification implemented fully here
}
Run Code Online (Sandbox Code Playgroud)
现在我在我的视图模型中创建了一个'ConccClass'集合,并在视图中使用xaml上的datagrid绑定它.
问题当我在后台线程上添加一个项目而没有任何dispact时它不会反映在datagrid中.表示没有添加任何项目 Todo这个我必须在Dispatcher中添加项目.BeginInvoke的.这对我来说很有意义.
但要更新任何物品的名称,我不需要调度员.
Task.Factory.StartNew(() =>
{
while (true)
{
Thread.Sleep(100);
{
this.Dispatcher.Invoke(() => this.Coll.Add(new TestTherad())); // **Works well**
//this.Coll.Add(new TestTherad()); // **does not work at all.**
this.Coll[0].Name = r.Next().ToString(); // ** without dispatcher works well.**
}
}
});
Run Code Online (Sandbox Code Playgroud)
为何如此行为?
以下是一个简短的解释:
您可能有一个绑定到可观察集合的UI元素.将元素添加到observable集合时,UI会更新以反映更改.但是,允许对UI进行更改的唯一线程是主线程.
因此,当您使用后台线程将项添加到observable集合时,UI会尝试使用后台线程进行更新,后台线程不允许对UI进行更改,并且会引发异常.
我很确定这行应该抛出异常://this.Coll.Add(new TestTherad());. 尝试在任务块内部进行调试.
当您使用调度程序时,您使用主线程进行更新,因此它可以正常工作.
对属性的更新有效,因为您只是在举办活动.框架应该监听该事件并确保自动将其分发给主线程.