Winform 让跨线程访问变得更简单
Winform 让跨线程访问变得更简单
前言
由于多线程可能导致对控件访问的不一致,导致出现问题。C#中默认是要线程安全的,即在访问控件时需要首先判断是否跨线程,如果是跨线程的直接访问,在运行时会抛出异常。近期在项目中碰到这个问题,首先想到的是,关闭跨线程检查,因为做的Winform没有多么复杂,图省事就直接这样做了,之后又出了一点点问题,还是必需通过委托的方式来实现。
资源下载
解决跨线程访问:
网上的资料很多,这里直接摘抄。
1、关闭跨线程检查。
2、通过委托的方式,在控件的线程上执行。
具体的代码如下:

using System;
using System.Threading;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
//方法一:不进行跨线程安全检查
CheckForIllegalCrossThreadCalls = false;
} private void button1_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(new ThreadStart(CalNum));
th1.Start();
} private void CalNum()
{
SetCalResult(DateTime.Now.Second);
} //方法二:检查是否跨线程,然后将方法加入委托,调用委托
public delegate void SetTextHandler(int result);
private void SetCalResult(int result)
{
if (label2.InvokeRequired == true)
{
SetTextHandler set = new SetTextHandler(SetCalResult);//委托的方法参数应和SetCalResult一致
label2.Invoke(set, new object[] { result }); //此方法第二参数用于传入方法,代替形参result
}
else
{
label2.Text = result.ToString();
}
}
}
}

改进
在我的Winform程序中,子线程涉及到对多个控件的更改,于是封装了一下,我这里使用的是拓展方法,只有在.net 3.5上才能支持,如果是.net2.0的环境,需要添加
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
public class ExtensionAttribute : Attribute { }
}
封装如下:

using System.Threading;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public static class Class1
{
/// <summary>
/// 跨线程访问控件 在控件上执行委托
/// </summary>
/// <param name="ctl">控件</param>
/// <param name="del">执行的委托</param>
public static void CrossThreadCalls(this Control ctl, ThreadStart del)
{
if (del == null) return;
if (ctl.InvokeRequired)
ctl.Invoke(del, null);
else
del();
}
}
}

具体的测试如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
var th = new Thread(() =>
{
//label1.Enabled = false;
label1.CrossThreadCalls(() => { label1.Enabled = !label1.Enabled; });
WriteMessage(DateTime.Now.ToString());
});
th.IsBackground = true;
th.Start();
} public void WriteMessage(string msg)
{
label1.CrossThreadCalls(() =>
{
label1.Text = msg;
});
}
}
}

这样一行代码就可以完成跨线程访问啦。

Winform 让跨线程访问变得更简单的更多相关文章
- Winform之跨线程访问控件(在进度条上显示字体)
此文章对于遇到必须使用线程但是没有办法在线程内操作控件的问题的处理 有很好的解决方案(个人认为的.有更好的方案欢迎交流.) 在做跨线程访问之前我们先了解下我们所做的需要达到的效果: 这个是批量的将x ...
- 实现 winform 异步跨线程访问UI控件
在开发winform时经常会用到多线程防止界面出现假死现象,比如当你单击某个按钮时,需要执行很多代码,但是在执行过程中想实时的将当前执行的情况报告给用户,类型进度条或文本什么的. 这个时候很显然,如果 ...
- 理解SynchronizationContext,如何在Winform里面跨线程访问UI控件
SynchronizationContext 类是一个基类,可提供不带同步的自由线程上下文. 此类实现的同步模型的目的是使公共语言运行库内部的异步/同步操作能够针对不同的异步模型采取正确的行为.此模型 ...
- C#WinForm解决跨线程访问控件属性报错
方式一(在程序初始化构造函数中加一行代码): public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCal ...
- winform 跨线程访问问题
一.问题描述 进行winform 开发我们在进行数据交换时避免不了使用多线程或异步方法,这样操作也将避免不了跨线程对控件进行操作(赋值.修改属性). 下面通过一个测试说明一下问题 点击一个按钮异步对t ...
- winform跨线程访问控件
首先说下,.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性.所以除了控件所在的线程外的线程调用会抛异常 (Cross-thread operation not va ...
- 如何跨线程访问Winform中的UI元素
如何跨线程访问Winform中的UI元素 假如制作一个Socket聊天应用程序,很可能会用到多线程: 例如为Receive方法开辟单独一个线程,例如为Receive方法开辟单独一个线程(后台运行的线程 ...
- WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object)
原文 WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object) 众所周知的,WPF 中多数对象都继承自 Dispatch ...
- C# WinFrom 跨线程访问控件
1.跨线程访问控件委托和类的定义 using System; using System.Windows.Forms; namespace ahwildlife.Utils { /// <summ ...
随机推荐
- C语言练手自己编写学生成绩管理系统
#include<stdio.h> #include<stdlib.h> /*定义学生结构体*/ struct Student { ]; ]; float Mark1; flo ...
- $.each()遍历Json对象
1.遍历JavaScript数组对象: var json = [ //中括号起始 {"id":"1","tagName":"app ...
- 响应式web前端框架Foundation & Bootstrap 对比
Foundation & Bootstrap都是易用.强大且灵活的前端框架,用于构建基于任何设备上的 Web 应用.提供流式布局,及多种 js UI 组件,如导航.表单.按钮.Tabs 等等. ...
- Windows下结束tomcat进程,dos命令
Microsoft Windows [版本 6.1.7601]版权所有 (c) 2009 Microsoft Corporation.保留所有权利. C:\Users\Administrator> ...
- js 正则之 判断密码类型
原文:js 正则之 判断密码类型 今天没啥写的,就分享个思路吧.之前在群里讨论的时候,谢亮兄弟说判断密码是否是纯数字,纯字母之类的.如果用 , 条判断,那就老长一大段了.这个思路是我之前看 jQuer ...
- .net使用cefsharp开源库开发chrome
.net使用cefsharp开源库开发chrome 离上篇写介绍pc端的混合开发和为什么以cefsharp入手研究混合开发已经有好几天,一直忙,抽不出时间继续写怎么搭建cefsharp开发环境.其实没 ...
- C#用Open与Add方法打开word文档的区别
C#打开word文档常用有两种方法:Add与Open. Microsoft.Office.Interop.Word._Document doc = (Document)appWord.Document ...
- leetcode第28题--Divide Two Integers
Divide two integers without using multiplication, division and mod operator. 分析:题目意思很容易理解,就是不用乘除法和模运 ...
- INNO SETUP卸载程序中加入自定义窗体
原文:INNO SETUP卸载程序中加入自定义窗体 [Setup] AppName=My Program AppVerName=My Program v.1.2 DefaultDirName={pf} ...
- SQL去掉小数点有效数字后的所有0
原文:SQL去掉小数点有效数字后的所有0 第一种方法 select cast(2.5000000000000 as real) select cast(2 as real) select ...