Winfrom 如何安全简单的跨线程更新控件
来源:http://www.cnblogs.com/rainbowzc/archive/2010/09/29/1838788.html
由于多线程可能导致对控件访问的不一致,导致出现问题。C#中默认是要线程安全的,即在访问控件时需要首先判断是否跨线程,如果是跨线程的直接访问,在运行时会抛出异常。
解决办法有两个:
1、不进行线程安全的检查
2、通过委托的方式,在控件的线程上执行
常用写法:(不安全)
private void WriteToolStripMsg(string msg, Color color)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(delegate()
{
toolStripMsg.Text = msg;
toolStripMsg.ForeColor = color; }));
}
else
{
toolStripMsg.Text = msg;
toolStripMsg.ForeColor = color;
}
} private void btnLogin_Click(object sender, EventArgs e)
{ string userName = this.txtUserName.Text.Trim();
string pwd = this.txtPwd.Text.Trim(); if (userName.IsNullOrEmpty())
{
WriteToolStripMsg("请输入登录名...", Color.Red);
this.txtUserName.Focus();
return;
}
if (pwd.IsNullOrEmpty())
{
WriteToolStripMsg("请输入密码...", Color.Red);
this.txtPwd.Focus();
return;
} if (userName.IsNotEmpty() && pwd.IsNotEmpty())
{
WriteToolStripMsg("系统正在登陆中...", Color.Blue);
this.btnLogin.BtnEnabled = false;
string msg = string.Empty;
Thread t = new Thread(() =>
{
//判断用户登录是否成功。
string restulMsg = string.Empty;
restulMsg = DataCenterService.Instance.Login(userName, pwd);
if (restulMsg.IsNullOrEmpty())
{
SysUser.CurrUserEntity = DataCenterService.Instance.GetInfoForName(userName);
this.DialogResult = DialogResult.OK;
}
else
{
WriteToolStripMsg(restulMsg, Color.Red);
this.BeginInvoke(new MethodInvoker(delegate()
{
this.btnLogin.BtnEnabled = true;
}));
}
});
t.IsBackground = true;
t.Start();
}
}
上述写法并不是最安全的,存在一定的问题。
推荐写法:
delegate void UpdateShowInfoDelegate(System.Windows.Forms.TextBox txtInfo, string Info);
/// <summary>
/// 显示信息
/// </summary>
/// <param name="txtInfo"></param>
/// <param name="Info"></param>
public void ShowInfo(System.Windows.Forms.TextBox txtInfo, string Info)
{
if (this.InvokeRequired)
{
//this.BeginInvoke(new MethodInvoker(delegate()
//{
// txtInfo.AppendText(Info);
// txtInfo.AppendText(Environment.NewLine + "\r\n");
// txtInfo.ScrollToCaret();
//}));
Invoke(new UpdateShowInfoDelegate(ShowInfo), txtInfo,Info);
return;
}
else
{
txtInfo.AppendText(Info);
txtInfo.AppendText(Environment.NewLine + "\r\n");
txtInfo.ScrollToCaret();
}
}
How to update the GUI from another thread in C#?
本文转载:http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c
跨线程时使用静态扩展方法更新控件
在CodeProject上看一个跨线程更新的方法,备忘一下。
如果在应用中存在较多简单的跨线程操作,下面的方法可能比较实用:
public static class ExtensionMethod
{
/// <summary>
/// 有返回值的扩展方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="isi"></param>
/// <param name="call"></param>
/// <returns></returns>
public static TResult SafeInvoke<T, TResult>(this T isi, Func<T, TResult> call) where T : ISynchronizeInvoke
{
if (isi.InvokeRequired) {
IAsyncResult result = isi.BeginInvoke(call, new object[] { isi });
object endResult = isi.EndInvoke(result); return (TResult)endResult;
}
else
return call(isi);
}
/// <summary>
/// 没有返回值的扩展方法
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="isi"></param>
/// <param name="call"></param>
public static void SafeInvoke<T>(this T isi, Action<T> call) where T : ISynchronizeInvoke
{
if (isi.InvokeRequired) isi.BeginInvoke(call, new object[] { isi });
else
call(isi);
}
}
然后在使用时就可以使用匿名委托很方便的操作:
lblProcent.SafeInvoke(d => d.Text = textForLabel);
progressBar1.SafeInvoke(d => d.Value = i);string labelText = lblProcent.SafeInvoke(d => d.Text);静态的扩展类方法使用泛型模板扩展像所有可继承 ISynchronizeInvoke 接口的控件,几乎适用于常见的所有控件呦 (来自 CodeProject 为所有类型的更新创建异步委托)
原始地址:http://www.codeproject.com/Articles/52752/Updating-Your-Form-from-Another-Thread-without-Cre
Winfrom 如何安全简单的跨线程更新控件的更多相关文章
- C#跨线程操作控件的最简单实现探究
随着程序复杂度的提高,程序不可避免会出现多个线程,此时就很可能存在跨线程操作控件的问题. 跨线程操作UI控件主要有三类方式: 1.禁止系统的线程间操作检查.(此法不建议使用) 2.使用Invoke(同 ...
- C# WinFrom 跨线程访问控件
1.跨线程访问控件委托和类的定义 using System; using System.Windows.Forms; namespace ahwildlife.Utils { /// <summ ...
- C# 跨线程调用控件
在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应. 同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线程间操作无效 第一种办法:禁 ...
- 【转载】C# 跨线程调用控件
转自:http://www.cnblogs.com/TankXiao/p/3348292.html 感谢原作者,转载以备后用 在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停 ...
- C# 跨线程调用控件的4中方法
原文:C# 跨线程调用控件 在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应. 同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线 ...
- winform跨线程访问控件
首先说下,.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性.所以除了控件所在的线程外的线程调用会抛异常 (Cross-thread operation not va ...
- C# 跨线程对控件赋值
第一种 跨线程对控件赋值 private void button2_Click(object sender, EventArgs e) { Thread thread1 = new Thread(ne ...
- C# 跨线程访问控件(MethodInvoker)
参考:https://www.cnblogs.com/lvdongjie/p/5428815.html .Net 通常禁止跨线程访问控件,设置Control.CheckForIllegalCrossT ...
- WinForm中新开一个线程操作 窗体上的控件(跨线程操作控件)
最近在做一个winform的小软件(抢票的...).登录窗体要从远程web页面获取一些数据,为了不阻塞登录窗体的显示,开了一个线程去加载数据远程的数据,会报一个错误"线程间操作无效: 从不是 ...
随机推荐
- BZOJ1861[ZJOI2006]Book书架
Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...
- maven的安装,maven库配置和Eclipse插件的安装
maven的安装,maven库配置和Eclipse插件的安装 1.下载并解压maven 2.配置环境变量 3.配置maven配置文件 1.下载链接 Downloading Apache Maven 2 ...
- 8月1日起,这些新政将影响移动互联网产业-b
今天,国家互联网信息办公室发布<移动互联网应用程序信息服务管理规定>.这项规定将从8月1日起生效,其中侧重对两类玩家提出了监管意见,他们分别是: 移动互联网应用程序提供者,即提供信息服务的 ...
- 30年的Hello world
30 年的 Hello world 转载自:http://www.admin10000.com/document/2398.html 最近我在7月4日这一天所在的那周休假了.休假期间,我利用大把的时间 ...
- Qt HTTP内部构架
QUrl url("http://qt.gitorious.org"); QNetworkRequest request(url); QNetworkAccessManager m ...
- 【转】WPF中Binding的技巧(一)
WPF中Binding的技巧(一) 在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到 ...
- sap中用函数增加断点(break point)
如果在增强程序中,每次调试都要去程序里面设置断点很麻烦,为了解决这个问题,可以用下面的两个方法: 1: if sy-uname eq 'XXXX' "XXX 为账号名字 break ...
- linux网络配置正确,能够ping通内网地址,无法打开外网网页
在虚拟机里面装了linux后,发现内网能访问,外网访问不了. 首先确定网络配置没有问题,并且能够访问外网,通过以下方法进行确认: [root@localhost ~]# more /etc/sysco ...
- 【Xamarin开发 Android 系列 6】 Android 结构基础(上)
原文:[Xamarin开发 Android 系列 6] Android 结构基础(上) 前面大家已经熟悉了什么是Android,而且在 [Xamarin开发 Android 系列 4] Android ...
- SectionIndexer中的getSectionForPosition()与getPositionForSection()
大家在做字母索引的时候常常会用到SectionIndexer这个类,里面有2个重要的方法 1. getSectionForPosition()通过该项的位置,获得所在分类组的索引号 2. getP ...