问题介绍

当ObservableCollection列表被UI线程占用时,如果在异步线程中调用ObservableCollection,会弹出以下异常:

问题分析

我们使用一个viewModel,在ViewModel中添加ObservableCollection类型的ItemsSource列表。

在列表使用ListBox绑定ItemsSource列表。再由界面触发对ItemsSource的修改。

     public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> _itemsSource = new ObservableCollection<string>(); public ObservableCollection<string> ItemsSource
{
get => _itemsSource;
set
{
_itemsSource = value;
OnPropertyChanged();
}
} public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

1. 直接在异步线程下修改ObservableCollection--报错

     private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var viewModel = this.DataContext as ViewModel;
Task.Run(() =>
{
//此段调用异常
viewModel.ItemsSource.Add("test1");
});
}

2. 在异步线程下,赋值ObservableCollection--正常

     private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var viewModel = this.DataContext as ViewModel;
Task.Run(() =>
{
//此段不会报错
var list = viewModel.ItemsSource.ToList();
list.Add("test0");
viewModel.ItemsSource = new ObservableCollection<string>(list);
});
}

3. 在异步线程下,赋值ObservableCollection后,再修改ObservableCollection--正常

     private void Button1_OnClick(object sender, RoutedEventArgs e)
{
var viewModel = this.DataContext as ViewModel;
Task.Run(() =>
{
//此段不会报错
viewModel.ItemsSource = new ObservableCollection<string>(new List<string>() { "test3", "test2" });
//此段不会报错
viewModel.ItemsSource.Add("test4");
});
}

在异步线程下设置的ItemsSource,可以被当前异步线程调用。

4. 异步线程下赋值ObservableCollection,然后在UI线程修改ObservableCollection--正常

         private void Button1_OnClick(object sender, RoutedEventArgs e)
{
var viewModel = this.DataContext as ViewModel;
Task.Run(() =>
{
//此段不会报错
viewModel.ItemsSource = new ObservableCollection<string>(new List<string>() { "test0" });
});
} private void Button2_OnClick(object sender, RoutedEventArgs e)
{
var viewModel = this.DataContext as ViewModel;
//此段不会报错
viewModel.ItemsSource.Add("test2");
}

在异步线程下设置的ItemsSource,可以被UI线程调用。此处可以理解为,赋值时,框架默默转到UI线程处理了?

但是上面3流程,为何正常,so weird~

5. 异步线程下,回到UI线程中,修改ObservableCollection--正常

     private void Button1_OnClick(object sender, RoutedEventArgs e)
{
var viewModel = this.DataContext as ViewModel;
Task.Run(() =>
{
Application.Current.Dispatcher.Invoke(() =>
{
//此段不会报错
viewModel.ItemsSource.Add("test");
});
});
}

WPF ObservableCollection 异步调用问题的更多相关文章

  1. WPf ObservableCollection异步调用问题

    当ObservableCollection列表被UI线程占用时,如果在异步线程中调用ObservableCollection,会弹出以下异常: private void Button1_OnClick ...

  2. Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token

    原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf?   因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...

  3. 【ASP.NET Web API教程】3.3 通过WPF应用程序调用Web API(C#)

    原文:[ASP.NET Web API教程]3.3 通过WPF应用程序调用Web API(C#) 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本博客文章,请先看前面的 ...

  4. 如何实现异步调用WCF

    在面向服务的.NET开发中,我们经常要调用WCF服务加载数据,这时候,如果使用同步调用,会阻止UI,影响用户体验UE/UX,而且当服务器ping不通或者网速特别烂的情况下,这时候基本上是处于卡死状态, ...

  5. Windows 8 应用开发 - 异步调用

    原文:Windows 8 应用开发 - 异步调用     不论是桌面客户端还是Web应用通常会出现处理时间较长的操作,为了在这段时间内不影响用户与应用之间的交互体验,开发人员通常会使用异步调用技术,使 ...

  6. silverlight——多次异步调用的顺序执行

    遇到这样一个功能需求,对于后台的同一个服务调用多次,但要求传入的参数能够再一个执行完之后再进行另一个参数的执行. 由于silverlight支持的是异步调用机制,故无法控制服务调用何时返回.那么如果使 ...

  7. C#委托异步调用

    参考页面: http://www.yuanjiaocheng.net/webapi/mvc-consume-webapi-get.html http://www.yuanjiaocheng.net/w ...

  8. Direct3D Draw函数 异步调用原理解析

    概述 在D3D10中,一个基本的渲染流程可分为以下步骤: 清理帧缓存: 执行若干次的绘制: 通过Device API创建所需Buffer: 通过Map/Unmap填充数据到Buffer中: 将Buff ...

  9. 一个简单的webservice的demo(下)winform异步调用webservice

    绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...

随机推荐

  1. monkey-----停止正在测试的monkey

    第一步:adb   shell ps | grep monkey:查找到正在测试的monkey包名   第二步:kill   pid:删除查找出的monkey进程   以上完美的停止monkey测试

  2. hystrix 结果缓存机制(5)

    hystrix支持将一个请求结果缓存起来,下一个具有相同key的请求将直接从缓存中取出结果,减少请求开销.要使用hystrix cache功能 第一个要求是重写getCacheKey(),用来构造ca ...

  3. Docker入门学习

    Python爬虫 最近断断续续的写了几篇Python的学习心得,由于有开发经验的同学来说上手还是比较容易,而且Python提供了强大的第三方库,做一个小的示例程序还是比较简单,这不我之前就是针对Pyt ...

  4. Spring Boot 2.X 如何快速集成单元测试?

    本文将详细介绍下使用Spring Boot 2.X 集成单元测试,对API(Controller)测试的过程. 一.实现原理 使用MockMvc发起请求,然后执行API中相应的代码,在执行的过程中使m ...

  5. 在Docker中体验数据库之Microsoft SQL Server

    前面记录了一下在docker中体验mongodb和mysql.今天记录一下mssql……其实早就体验了,就是没有记录,前几天看了一下2019的一些新闻,很喜欢Polybase这个特性,想体验一把,可惜 ...

  6. 阿里云RDS for SQL Server测试吐槽

    最近测试了一下阿里云RDS for SQL Server,有些设计简直就是反人类,让人不得不吐槽一番. 1:控制台创建数据库时,数据库名不能包含大小字母. 如上截图所示,数据库名称不能包含大写字母,好 ...

  7. 【原】Java学习笔记034 - 网络

    package cn.temptation; import java.net.InetAddress; public class Sample01 { public static void main( ...

  8. 使用async await 封装 axios

    异步变同步: 厉害-- https://www.jianshu.com/p/4168efdc172b

  9. 教程二 网页和lua交互修改openwrt

    硬件 http://zhan.renren.com/h5/entry/3602888498044209332 GL-iNet 1 首先安装 webserver之lighttpd  ,openwrt自带 ...

  10. C# 定时关机小程序

    1.打开VS2019,创建界面和按钮 2. 代码如下: private void button1_Click(object sender, EventArgs e) { downpc(txttime. ...