使用 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. django之cookies,session 、中间件及跨站请求伪造

    cookies 和session 为什么会有cookie? ​ 由于http协议是无状态的,即用户访问过后,不留痕迹(状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被 ...

  2. BOI 2003 团伙

    洛谷 P1892 [BOI2003]团伙 洛谷传送门 题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋 ...

  3. Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) 题解

    Happy Birthday, Polycarp! Make Them Odd As Simple as One and Two Let's Play the Words? Two Fairs Bea ...

  4. Linux设置定时任务方法

    linux下定时执行任务的方法: 在LINUX中你应该先输入crontab -e,然后就会有个vi编辑界面,再输入0 3 * * 1 /clearigame2内容到里面 :wq 保存退出.   在LI ...

  5. 团队作业第五次—项目冲刺-Day2

    Day2 part1-SCRUM: 项目相关 作业相关 具体描述 所属班级 2019秋福大软件工程实践Z班 作业要求 团队作业第五次-项目冲刺 作业正文 hunter--冲刺集合 团队名称 hunte ...

  6. java byte[]和base64互相转换

      1.方式一 import java.io.UnsupportedEncodingException; import java.util.Base64; // byte[]转base64 Strin ...

  7. mysql Duplicate entry '9223372036854775807' for key 'PRIMARY'

    mysql插入数据报错提示: ERROR 1062(23000) Duplicate entry  '9223372036854775807' for key 'PRIMARY' 发现问题果断 直接 ...

  8. (五)golang--常用的一些玩意

    \t--制表位 \n--换行符 \\--一个\ \"--一个” \r--回车 行注释://,一次性注释多行指令,选中代码后ctrl+/ 块注释:/* */ 代码规范: (1)官方推荐使用行注 ...

  9. linux centos安装教程

    linux centos安装教程1 CentOS-7-x86_64-DVD-1511.iso 这个是dvd版本 2 CentOS-7-x86_64-Minimal-1511.iso 这个迷你版 是没有 ...

  10. 《 .NET并发编程实战》阅读指南 - 第1章

    先发表生成URL以印在书里面.等书籍正式出版销售后会公开内容.