使用 async/await 的情况:

private async void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).IsEnabled = false;
const string do7zCmd = @"a D:\x7zaTest.7z"
+ @" E:\WpfApp1\WpfApp1\bin\Debug\*.dll"
+ @" E:\WpfApp1\WpfApp1\bin\Debug\*.xml"
; tex1.Text = "Running...";
tex1.Focus(); var ret = await Task.Run(() => X7za.Do7z(do7zCmd)); //更新UI线程的操作
tex1.Text += "\r\n" + ret + "\r\n" + do7zCmd;
(sender as Button).IsEnabled = true;
}

在不使用 async/await 的情况下有 3 种办法:

private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).IsEnabled = false;
const string do7zCmd = @"a D:\x7zaTest.7z"
+ @" E:\WpfApp1\WpfApp1\bin\Debug\*.dll"
+ @" E:\WpfApp1\WpfApp1\bin\Debug\*.xml"
; //更新UI线程的操作
var f = new Action<int>(ret =>
{
tex1.Text += "\r\n" + ret + "\r\n" + do7zCmd;
(sender as Button).IsEnabled = true;
}); //1.BackgroundWorker - 推荐,有进度报告机制,对 UI 的操作在创建线程内
var b = new BackgroundWorker();
b.DoWork += (o, args) => args.Result = X7za.Do7z(do7zCmd);
b.RunWorkerCompleted += (o, args) => f((int)args.Result);
b.RunWorkerAsync(); //2.委托异步执行 - 主要就是下面的 BeginInvoke 调用,
//这是从 BackgroundWorker 的源码里挖出来的用法。
//
//这个片段对 UI 线程的操作是在别的线程通过 WPF
//Application 对象的 Dispatcher 机制跨线程执行的。
new Action(() =>
{
var ret = X7za.Do7z(do7zCmd);
Application.Current.Dispatcher.Invoke(() => f(ret));
}).BeginInvoke(null, null); //3.Task.Run - 很通俗的方法了。对 UI 的操作跟片段2一样。
Task.Run(() =>
{
var ret = X7za.Do7z(do7zCmd);
Application.Current.Dispatcher.Invoke(() => f(ret));
}); tex1.Text = "Running...";
tex1.Focus();
}

就是酱紫。
推荐第一种,WinForm 程序也可以用。

【WPF异步更新UI的两种方法】

首先强调一点:异步更新UI实际上就是新开一个线程,执行耗时的任务,但是UI上的东西又不能被其他线程访问,所以非UI线程分析UI的那几条代码用一种特殊的方法来执行,从而实现既可以将耗时的操作放在其他线程,有可以更新UI。

1、方法一
案例:UI上有三个TextBlock,一个Button,当点击button的时候新三个task产生随机数(模拟耗时操作),然后将产生的随机数给UI显示

        private void Button_Click(object sender, RoutedEventArgs e)
{
//也可以Task task = new Task(SchedulerWork);task .Start()
Task.Factory.StartNew(SchedulerWork);
} private void SchedulerWork()
{
//fistr,second,three是三个TextBlock控件的名字
Task task = new Task((tb) => Begin(this.first), this.first);
Task task2 = new Task((tb) => Begin(this.second), this.first);
Task task3 = new Task((tb) => Begin(this.Three), this.first);
task.Start();
task2.Start();
task3.Start();
Task.WaitAll(task, task2, task3);
} private void Begin(TextBlock tb)
{
int i = ;
while (i > )
{
i--;
}
Random random = new Random();
String Num = random.Next(, ).ToString();
this.Dispatcher.BeginInvoke(new Action(() => tb.Text = Num));
}

主要注意的几点:
1、Begin方法不是在UI线程上执行的,所以他里面不能访问UI上的元素,也就是不能执行tb.Text = Num,否则他就是会报异常:(A first chance exception of type ‘System.InvalidOperationException’ occurred in WindowsBase.dll
Additional information: The calling thread cannot access this object because a different thread owns it.)
2、因此我们更新UI的部分采用:
this.Dispatcher.BeginInvoke(new Action(() => tb.Text = Num));
方法来进行更新,这样实际上就交给UI线程来做了,也就不会报错了。
2 方法二 
直接上代码

        private void Button_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(SchedulerWork);
} private readonly TaskScheduler _syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); private void SchedulerWork()
{
Task task = new Task((tb) => Begin(this.first), this.first);
Task task2 = new Task((tb) => Begin(this.second), this.first);
Task task3 = new Task((tb) => Begin(this.Three), this.first);
task.Start();
task2.Start();
task3.Start();
Task.WaitAll(task, task2, task3);
} private void Begin(TextBlock tb)
{
int i = ;
while (i > )
{
i--;
}
Random random = new Random();
String Num = random.Next(, ).ToString();
Task.Factory.StartNew(() => tb.Text = Num, new CancellationTokenSource().Token, TaskCreationOptions.None, _syncContextTaskScheduler).Wait();
}

【转】WPF 异步执行方法后对 UI 进行更新的几种方法的更多相关文章

  1. VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法

    原文:VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/det ...

  2. WPF编程,使用WindowChrome实现自定义窗口功能的一种方法。

    原文:WPF编程,使用WindowChrome实现自定义窗口功能的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/arti ...

  3. c++学习笔记之基础---类内声明函数后在类外定义的一种方法

    在C++的“类”中经常遇到这样的函数, 返回值类型名 类名::函数成员名(参数表){ 函数体.} 双冒号的作用 ::域名解析符!返回值类型名 类名::函数成员名(参数表) { 函数体. } 这个是在类 ...

  4. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  5. WPF 异步执行

    private void Operate_OnClick(object sender, RoutedEventArgs e) { AsyncFindBox(); RadWindow.Alert(&qu ...

  6. 代码操作Word时,目录自动更新的两种方法

    最近的项目中有一个功能点为:根据分析数据库并生成报告.不过不是大数据.数据挖掘之类,报告的内容.组织方式都是事先固定下来的.实现的方式为,在普通word文档中插入书签制成模板,然后程序使用OpenXM ...

  7. mysql 批量更新的四种方法

    批量更新的方法: 1 ) 逐条更新 代码如下: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other_value'; 如果更新 ...

  8. 在JS方法中返回多个值的三种方法

    在使用JS编程中,有时需要在一个方法返回两个个或两个以上的数据,用下面的几种方法都可以实现: 1 使用数组的方式,如下: <html> <head> <title> ...

  9. 在JS方法中返回多个值的三种方法(转载)

    来源:https://www.cnblogs.com/gxsyj/p/6004574.html 在使用JS编程中,有时需要在一个方法返回两个个或两个以上的数据,用下面的几种方法都可以实现: 1 使用数 ...

随机推荐

  1. 编译安装PHP以及需要的基本扩展库(php7.4)

    安装配置选项1: ./configure --prefix=/usr/local/php --with-mysql=/usr/local/mysql --with-curl --with-freety ...

  2. 【Spring AOP】切入点表达式(四)

    一.切入点指示符 切入点指示符用来指示切入点表达式目的,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指示符如下: execution:用于匹配方 ...

  3. flask回顾

    pip install flask from flask import Flask app = Flask(__name__) # 命令行启动,用manager,访问会变的非常慢 pip instal ...

  4. Emacs奇技淫巧

    奇技快捷键 C-t: 交换两个字符的位置 M-t: 交换两个字符的位置 C-x, C-t: 则是交换两行的位置 C-x, h: 全选 M-/: 匹配这个首字母的单词 M-c: 将下一个单词开头大写, ...

  5. 日常笔记3关于bool类型数组初始化的问题

    一般会有两种考虑,全为true或全为false 赋值方式: <1>memset(boolArray,0,sizeof(Array)); 头文件:#include<cstring> ...

  6. 第02组 Beta冲刺(4/4)

    队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:了解整个游戏的流程 GitHub签入记录 接下来的计划:继续完成游戏 还剩下哪些任务:完成游戏 燃尽图 遇到的困难:没有美术比较好的 ...

  7. 【灵魂拷问】你为什么要来学习Node.js呢?

    [灵魂拷问]你为什么要来学习Node.js呢? 学习node.js适合的人群: 需要必备一些HTML,CSS,JavaScript及编程有一定程度了解的读者阅读,一些简单的命令行操作,具备服务端开发经 ...

  8. 网络1911、1912 C语言第5次作业--循环结构 批改总结

    如题 一.评分规则 1.伪代码务必是文字+代码描述,直接反应代码,每题扣1分 2.提交列表没内容,或者太简单,每题得分0分.注意选择提交列表长的题目介绍. 3.代码格式不规范,包括命名随意.继续扣分. ...

  9. [LeetCode] 36. Valid Sudoku 验证数独

    Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to th ...

  10. redis持久化方式与优缺点

    Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化.redis支持四种持久化方式,一是 Snapshotting(快照)也是默认方式:二是Appen ...