c# winform编程之多线程ui界面资源修改总结篇【转】
c# winform编程之多线程ui界面资源修改总结篇
单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么做,比如:
private void btnSet_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ParameterizedThreadStart(SetTextBoxValue));
//当然也可以用匿名委托写成Thread t = new Thread(SetTextBoxValue);
t.Start("Hello World");
}
void SetTextBoxValue(object obj)
{
this.textBox1.Text = obj.ToString();
}
运行时,会报出一个无情的错误:
线程间操作无效: 从不是创建控件“textBox1”的线程访问它。
究其原因,winform中的UI控件不是线程安全的,如果可以随意在任何线程中改变其值,你创建一个线程,我创建一个线程,大家都来抢着更改"TextBox1"的值,没有任何秩序的话,天下大乱...
解决办法:
1.掩耳盗铃法(Control.CheckForIllegalCrossThreadCalls = false;)--仅Winform有效
using System;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键
}
private void btnSet_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ParameterizedThreadStart(SetTextBoxValue));
t.Start("Hello World");
}
void SetTextBoxValue(object obj)
{
this.textBox1.Text = obj.ToString();
}
}
}
设置Control.CheckForIllegalCrossThreadCalls为false,相当于不检测线程之间的冲突,允许各路线程随便乱搞,当然最终TextBox1的值到底是啥难以预料,只有天知道,不过这也是最省力的办法
2.利用委托调用--最常见的办法(仅WinForm有效)
using System;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
delegate void D(object obj);
public Form1()
{
InitializeComponent();
}
private void btnSet_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ParameterizedThreadStart(SetTextBoxValue));
t.Start("Hello World");
}
void SetTextBoxValue(object obj)
{
if (textBox1.InvokeRequired)
{
D d = new D(DelegateSetValue);
textBox1.Invoke(d,obj);
}
else
{
this.textBox1.Text = obj.ToString();
}
}
void DelegateSetValue(object obj)
{
this.textBox1.Text = obj.ToString();
}
}
}
3.利用SynchronizationContext上下文 -- 最神秘的方法(Winform/Silverlight能用)
之所以说它神秘,是因为msdn官方对它的解释据说也是不清不楚
using System;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnSet_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ParameterizedThreadStart(Run));
MyPram _p = new MyPram() { context = SynchronizationContext.Current, parm = "Hello World" };
t.Start(_p);
}
void Run(object obj)
{
MyPram p = obj as MyPram;
p.context.Post(SetTextValue, p.parm);
}
void SetTextValue(object obj)
{
this.textBox1.Text = obj.ToString();
}
}
public class MyPram
{
public SynchronizationContext context { set; get; }
public object parm { set; get; }
}
}
4.利用BackgroundWorker --最偷懒的办法(Winform/Silverlight通用)
BackgroundWorker会在主线程之外,另开一个后台线程,我们可以把一些处理放在后台线程中处理,完成之后,后台线程会把结果传递给主线程,同时结束自己。
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnSet_Click(object sender, EventArgs e)
{
//MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync("Hello World");
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
//MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
e.Result = e.Argument;//这里只是简单的把参数当做结果返回,当然您也可以在这里做复杂的处理后,再返回自己想要的结果(这里的操作是在另一个线程上完成的)
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了
this.textBox1.Text = e.Result.ToString();
//MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
}
}
}
5.Dispatcher.BeginInvoke--Silverlight的独门秘籍
代码
using System.Threading;
using System.Windows.Controls;
using System.Windows.Input;
namespace ThreadTest
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Thread t = new Thread(SetTextValue);
t.Start("Hello World");
}
void SetTextValue(object text)
{
this.Dispatcher.BeginInvoke(() => { this.txt.Text = text.ToString(); });
}
}
}
https://www.cnblogs.com/zhangchenliang/archive/2012/03/15/2397984.html
c# winform编程之多线程ui界面资源修改总结篇【转】的更多相关文章
- c# winform编程之多线程ui界面资源修改总结篇
单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么 ...
- C# winform编程中多线程操作控件方法
private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...
- Android异步处理二:使用AsyncTask异步更新UI界面
在<Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面>中,我们使用Thread+Handler的方式实现了异步更新UI界面,这一篇中,我们介绍一种更为简 ...
- Ligg.EasyWinApp-100-Ligg.EasyWinForm:一款Winform应用编程框架和UI库介绍
本项目是一个Winform应用编程框架和UI库.通过这个该框架,不需任何代码,通过XML配置文件,搭建任意复杂的Windows应用界面,以类似Execel公式的方式实现基本的过程控制(赋值.条 ...
- C# Winform 跨线程更新UI控件常用方法汇总(多线程访问UI控件)
概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的线程访问它”的异常.处理跨线程更新Winform UI控件常用的方法有4种:1. ...
- C#-WinForm跨线程修改UI界面
待解决的问题 在我做WinForm开发的过程中,经常会遇到耗时操作或阻塞操作.他们会引发软件的卡顿甚至假死,严重影响软件的使用. 因此,这类耗时或阻塞的操作一般都会使用异步的方式去执行,不影响主线程( ...
- 转载:21个免费的UI界面设计工具、资源及网站
我们刚刚介绍了移动设计初探:触屏网页设计.本文将介绍一些UI界面与设计使用的元素.软件和网站.内容很丰富,适合用户体验设计师.界面设计师.产品设计师.JS前段开发.手机产品设计以及iPad和平板电脑产 ...
- Winform非UI线程更新UI界面的各种方法小结
我们知道只有UI线程才能更新UI界面,其他线程访问UI控件被认为是非法的.但是我们在进行异步操作时,经常需要将异步执行的进度报告给用户,让用户知道任务的进度,不至于让用户误认为程序“死掉了”,特别是对 ...
- 【转】21个免费的UI界面设计工具、资源及网站
本文将介绍21个免费的UI界面设计工具.资源及网站,如果你在做用户体验设计.界面设计.产品设计.JS前段开发.手机产品设计以及iPad和平板电脑产品设计,不妨来看看. AD: 2013云计算架构师峰会 ...
随机推荐
- 基于五阶段流水线的RISC-V CPU模拟器实现
RISC-V是源自Berkeley的开源体系结构和指令集标准.这个模拟器实现的是RISC-V Specification 2.2中所规定RV64I指令集,基于标准的五阶段流水线,并且实现了分支预测模块 ...
- SpringBoot和微服务
SpringCloud SpringBoot 概念 应用 微服务CAP Consistency(数据强一致性),Availability(服务可用性),Partition-tolerance(分区容错 ...
- 转 SSM框架整合to萌新
作用: SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层 使用spring ...
- Git 统计提交代码行数
指定用户名 git log --author="your_name_here" --pretty=tformat: --numstat | awk '{ add += $1; su ...
- 如何破解安卓App
韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com 如何破解安卓App
- 【51nod-1239&1244】欧拉函数之和&莫比乌斯函数之和 杜教筛
题目链接: 1239:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 1244:http://www.51nod. ...
- python循环与判断
学习一门新的语言最重要的就是练习. 一.脚本需求: 编写登陆接口 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定 二.脚本流程图: 写代码之前画个流程图总是好的,可以让你理清思路,避免写着写着 ...
- hierarchyid有关的一些函数
于hierarchyid有关的一些函数主要有: GetAncestor :取得某一个级别的祖先 GetDescendant :取得某一个级别的子代 GetLevel :取得级别 ...
- ROS知识(11)----同步两台机器时钟
两台机器同时运行过程中,对于ROS的tf变换,其要求两台机器的时钟要保持一致. 1.查询时间 首先通过以下命令,看两台机器时钟是否有差异.在本机上,查看远程master的机器时间: ntpdate - ...
- Get started with IDA and disassembly SH7058
http://www.romraider.com/forum/viewtopic.php?f=25&t=6303 All of the 16-bit guidance in the follo ...