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云计算架构师峰会 ...
随机推荐
- Collabtive 系统 SQL 注入实验(补充)
SQL Injection:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令. 具体来说,它是利用现有应用程序,将(恶意)的SQL命令注 ...
- 二、django rest_framework源码之认证流程剖析
1 绪言 上一篇中讲了django rest_framework总体流程,整个流程中最关键的一步就是执行dispatch方法.在dispatch方法中,在调用了一个initial方法,所有的认证.权限 ...
- 使用Mongo索引需要注意的几个点
1.正则表达式和取反运算符不适合建立索引 正则表达式:$regex 取反运算符:$ne ,$nin 2.backgroud建立索引速度缓慢 前台创建是会有阻塞,backgroud效率缓慢,实际情况实际 ...
- 虚拟多Mac地址工具Multimac
虚拟多Mac地址工具Multimac Mac地址采用唯一标识标记网络的各种设备.在同一个时间内,Linux系统中的网卡只能使用一个Mac地址.在渗透测试中,为了隐藏自己的身份,往往需要以不同的Ma ...
- oslo.config
cfg Module来自于OpenStack中的重要的基础组件oslo.config,通过cfg Module可以用来通过命令行或者是配置文件来配置一些options, 对于每一个选项使用Opt类或者 ...
- python列表中中文编码的问题
在python2列表中,有时候,想打印一个列表,会出现如下显示: 这个是由于: print一个对象,是输出其“为了给人(最终用户)阅读”而设计的输出形式,那么字符串中的转义字符需要转出来,而且 也不要 ...
- django中缓存配置
# ======缓存配置====== CACHES = { ## 虚拟缓存,开发调试版本,此为开始调试用,实际内部不做任何操作 # 'default': { # 'BACKEND': 'django. ...
- virtualenv虚拟环境安装不同版本的django
在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4.所有第三方的包都会被pip安装到Python3的site-packages目录下. 如果我们要同时开发多个应用程序,那这 ...
- 射洪中学讲课PPT
咸鱼跑去射洪中学讲课去啦. 高中生好萌呀!!!! 下面是讲课PPT day3 简单吹了一波noip2015如何骗分,所以课件就是去网上到处kuai题解而已,所以课件我就不上传了. day4 题目+题解 ...
- Codeforces Round #283 (Div. 2) B. Secret Combination 暴力水题
B. Secret Combination time limit per test 2 seconds memory limit per test 256 megabytes input standa ...