c#执行异步操作
来源:互联网 发布:截取在线视频片段软件 编辑:程序博客网 时间:2024/05/29 21:28
转载自点击打开链接
Winform中的控件是绑定到特定的线程的(一般是主线程),这意味着从另一个线程更新主线程的控件不能直接调用该控件的成员。
控件绑定到特定的线程这个概念如下:
为了从另一个线程更新主线程的Windows Form控件,可用的方法有:
首先用一个简单的程序来示例,这个程序的功能是:在Winfrom窗体上,通过多线程用label显示时间。给出下面的两种实现方式
1.结合使用特定控件的如下成员
InvokeRequired属性:返回一个bool值,指示调用者在不同的线程上调用控件时是否必须使用Invoke()方法。如果主调线程不是创建该控件的线程,或者还没有为控件创建窗口句柄,则返回true。
Invoke()方法:在拥有控件的底层窗口句柄的线程上执行委托。
BeginInvoke()方法:异步调用Invoke()方法。
EndInvoke()方法:获取BeginInvoke()方法启动的异步操作返回值。
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace MutipleThreadTest{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } public delegate void ChangeTimeDelegate(Control c);//包装代理类 private void PrintTime() { if (label1.InvokeRequired == true) { while (true) { label1.Invoke(new ChangeTimeDelegate((Control c)=> c.Text = DateTime.Now.ToString() ) ,
new object[] {label1}); } } else while (true) { label1.Text = DateTime.Today.ToString(); } } private void Form1_Load(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(PrintTime));
t.IsBackground = true; t.Start(); } }}还可以使用backegroundworker控件
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace MutipleThreadTest{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } public delegate void ChangeTimeDelegate(Control c); private void Form1_Load(object sender, EventArgs e) { backgroundWorker1.RunWorkerAsync(); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { if (label1.InvokeRequired == true) { while (true) { label1.Invoke(new ChangeTimeDelegate((Control c) => c.Text = DateTime.Now.ToString()) , new object[] { label1 }); } } else while (true) { label1.Text = DateTime.Today.ToString(); } } }}
更新另一个线程的进度条示例(第一种方法实现)
DebugLZQ觉得第一种方法要更直观一点,或是更容易理解一点。下面再用第一种方法来做一个Demo:输入一个数,多线程计算其和值更新界面上的Label,并用进度条显示计算的进度。实际上就是,更新另一个线程的两个UI控件。
原博客使用的是new 一个线程实现的,这里我是用backgroundworker组件实现
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace MutipleThreadTest{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } public delegate void ChangeProgressDelegate(ProgressBar c,int s); public delegate void ChangeLabelDelegate(Control c, string s); private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { long num = Convert.ToInt64(e.Argument); long sum = 0; for(long i = 1; i <= num; i++) { sum += i; if(i % 100 == 0) { progressBar1.Invoke(new ChangeProgressDelegate((ProgressBar c,int s) => c.Value = s), new object[] { progressBar1, Convert.ToInt32((i * 100) / num) }); } } label1.Invoke(new ChangeLabelDelegate((Control c, string s) => { c.Text = s; }), new object[] { label1, sum.ToString() }); } private void button1_Click(object sender, EventArgs e) { backgroundWorker1.RunWorkerAsync(textBox1.Text); } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { progressBar1.Value = 0; textBox1.Text = ""; } }}
总觉得这样更新一个组件太麻烦了,又是代理进程的。不知道还有没有更好的办法。继续研究一下
0 0
- c#执行异步操作
- C#异步执行操作Helper
- C#用异步BackgroundWorker执行一个文本读取的操作
- C# 线程知识--使用Task执行异步操作
- C#执行异步操作的几种方式总结比较
- C# 线程知识--使用Task执行异步操作
- C# 方法异步执行
- 异步执行数据库操作
- 执行异步操作
- ThreadPool执行异步操作
- curl 异步执行操作
- 异步执行网络操作
- c#关于异步操作。
- C#异步操作sample1
- C#实现异步操作
- 浅析C#异步操作
- C# 异步操作
- C# 异步操作详解
- tensorflow tensorboard相关的资料
- 在catch中写处理!!
- 基于HTML5 FileReader创建图片上传预览图
- 设计模式之策略模式
- 开发OBS实录
- c#执行异步操作
- thInkphp 写入文件
- springboot-内置tomcat
- 基于TV模型的image inpainting算法
- 全排列延伸编程题目
- HttpCallUtil
- 发现一个不错的博客
- 第三章:字符串、向量和数组
- 线段树--区间合并hdu--1540