问题介绍

当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. ServletContextListener

    在 Servlet API 中有一个 ServletContextListener 接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期. 当Serv ...

  2. appium---【已解决】【Mac】如何查看java的安装路径及JAVA_HOME环境变量的配置

    报错截图:根据提示可以看出,JAVA_HOME的环境变量配置错误,需要重新配置. 1.查看Java版本 打开mac电脑,查看java版本,打开终端Terminal,通过命令查看java的版本 Luck ...

  3. APP版本更新通知流程测试要点

    一.APP版本更新通知流程图如下: 二.测试注意点: 1.Android更新直接下载APK,IOS引导至APP Store更新页面: 强制更新------只有"立即更新" 1.一般 ...

  4. set命令详解

    我们依然是围绕这几个话题展开学习: 1.什么是set命令? 2.为什么要用set命令? 3.怎样使用set命令? 1.什么是set命令? ♦ set命令作用主要是显示系统中已经存在的shell变量,以 ...

  5. 如何做好技术Team Leader

    背景 互联网公司的技术团队管理通常分为2个方向:技术管理和团队管理,互联网公司的技术TL与传统软件公司的PM还是有很大的区别,传统软件公司的PM更多注重于对项目的管理包括项目任务拆解.项目进度以及风险 ...

  6. 我眼中的 Nginx(五):Nginx — 子请求设计之道

    张超:又拍云系统开发高级工程师,负责又拍云 CDN 平台相关组件的更新及维护.Github ID: tokers,活跃于 OpenResty 社区和 Nginx 邮件列表等开源社区,专注于服务端技术的 ...

  7. C# 数组比较--取得两个集合的交集,差集,并集的方法

    方法关键字: 交集:Intersect 差集:Except 并集:Union 使用代码: , , , , }; , , , , }; var 交集 = arr1.Intersect(arr2).ToL ...

  8. FontAwesome 图标字体库的使用

    在前端开发中,许多新手常会遇见一个问题,参考的网页上有类似下图的图标,但在资源里却找不到对应的文件,这是因为这些网页使用了图标库.这里介绍一种常见的图标库——FontAwesome的使用. 1.登录F ...

  9. XSS Challenges xss-quiz.int21h.jp

    概述: https://xss-quiz.int21h.jp/ Stage #1 payload: <script>alert(document.domain);</script&g ...

  10. Hive的原理

    阅读目录 一.Hive内部表和外部表 1.Hive的create创建表的时候,选择的创建方式: - create table - create external table 2.特点: ● 在导入数据 ...