问题介绍

当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. java自动化-数据驱动juint演示,上篇

    本文旨在帮助读者介绍,一般的全自动化代码接口,并简单介绍如何使用数据驱动来实现简单的自动化 在经过上述几个博客介绍后,相信读者对自动启动执行一个java编译过的class有了一定了解,也完全有能力去执 ...

  2. Docker 发布 Abp net core web 服务

    Docker 发布 Abp net core web 服务 准备工作:Abp 项目,这个是模板下载地址 https://aspnetboilerplate.com/Templates (本例使用的是S ...

  3. 从壹开始微服务 [ DDD ] 之一 ║ D3模式设计初探 与 我的计划书

    缘起 哈喽大家周四好!又是开心的一天,时间过的真快,我们的 <从壹开始 .net core 2.1 + vue 2.5>前后端分离系列共 34 篇已经完结了,当然以后肯定还会有更新和修改, ...

  4. .Net Core 权限验证与授权(AuthorizeFilter、ActionFilterAttribute)

    在.Net Core 中使用AuthorizeFilter或者ActionFilterAttribute来实现登录权限验证和授权 一.AuthorizeFilter 新建授权类AllowAnonymo ...

  5. Python爬虫入门教程 57-100 python爬虫高级技术之验证码篇3-滑动验证码识别技术

    滑动验证码介绍 本篇博客涉及到的验证码为滑动验证码,不同于极验证,本验证码难度略低,需要的将滑块拖动到矩形区域右侧即可完成. 这类验证码不常见了,官方介绍地址为:https://promotion.a ...

  6. 解决Configuration 'compile' is obsolete and has been replaced with implementation

    项目中Gradle版本升级到4.4后,项目构建时,每次出现红色的警告信息: WARNING: Configuration 'compile' is obsolete and has been repl ...

  7. C# 添加Excel表单控件(Form Controls)

    在Excel中,添加的控件可以和单元格关联,我们可以操作控件来修改单元格的内容,在下面的文章中,将介绍在Excel中添加几种不同的表单控件的方法,包括: 添加文本框(Textbox) 单选按钮(Rad ...

  8. 基于geoserver样式服务实现图层要素自定义配图

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 在一般项目中,我们将geoserver样式服务中的SLD各参 ...

  9. Percona XtraBackup 8.0, 安装与测试

    Percona XtraBackup 8.0 是Percona XtraBackup新推出了一个针对MySQL8.0的版本,主要是MySQL8.0在Redo 和 数据库字典方面有了新的改进. Xtra ...

  10. 仓储repository概念

    1.为什么要用仓储?(仓储有什么用) 1.1 解耦 为了解耦领域层与数据映射层的关系. 1.2 管理增删查改 仓储模式最大的优点就是所有的数据访问首先是通过仓库的,对仓库的增删改都不会立即提交到数据库 ...