使用 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. USACO Building Roads

    洛谷 P2872 [USACO07DEC]道路建设Building Roads 洛谷传送门 JDOJ 2546: USACO 2007 Dec Silver 2.Building Roads JDOJ ...

  2. leetcode206. 反转链表

    1:迭代法 假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3. 在遍历列表时,将当前节点的 next 指针改为指向前一个元素.由于节点没有引用其上一个节点,因此必 ...

  3. 基于github发布 个人网站/博客

    我们可以使用GitHub去发布自己的网站了(静态网站), 只要经过简单几步即可.这样小伙伴可以给朋友或面试官展示自己个人项目啦. 第一步:创建一个新仓库 第二步:在仓库选择“Settings”页,找到 ...

  4. 动态规划 | 保留重复元素的LCS 1045

    这题也可以用LIS求解.LIS解题报告:动态规划 | 对输入进行hash处理的LIS 1045 普通LCS是必须完全匹配的,所以状态转移方程式(末端匹配到时):dp[i][j]=dp[i-1][j-1 ...

  5. kali linux2019.4 设置中文字体教程

    最近Kali linux更新到了2019.4版本,下载下来发现找不到设置中文的选项,经过在网上搜索一番发现一个开源的汉语字体包:文泉驿字体 在终端中输入以下命令 apt-get install ttf ...

  6. mysq-5.7忘记密码修改

    一,停止mysql /etc/init.d/mysqld stop 二,启动mysql mysqld_safe --skip-grant-tables 安全模式+免验证启动服务 三,登入mysql服务 ...

  7. Unity Shader 广告牌效果

    广告牌效果指的是,一个二维平面的法线方向始终与视线(摄像机的观察方向)相同.广泛运用于渲染烟雾,云朵,闪光等. 它的本质在于构建旋转矩阵,此时我们可以选择三个基向量来构建此矩阵. 指向→的方向(X轴) ...

  8. 安卓 apk 嵌入H5页面只显示部分

    安卓 apk 嵌入H5页面只显示部分(有空白页出现) 解决方案 没有加载的是js部分,需要在安卓那边加上一串代码 webView.getSetting().setDomStorageEnabled(t ...

  9. 集合类源码(六)Map(HashMap, Hashtable, LinkedHashMap, WeakHashMap)

    HashMap 内部结构 内部是一个Node数组,每个Node都是链表的头,当链表的大小达到8之后链表转变成红黑树. put操作 final V putVal(int hash, K key, V v ...

  10. [完整版]Postgresql 数据库 备份以及恢复的过程

    0. 准备工作 linux机器上面 必须安装上pg数据库 然后 需要将 pg的主程序目录 放到环境变量里面去 便于执行命令. 1. 先备份 . 备份目标数据库: pg_dump -h -F c -f ...