c# Winform 多线程操作
主要是对一个过程需要的时间很长执行时会出现界面假死的情况
方法1:
Application.DoEvents(),这种方法当你拖动窗体时,界面不会假死。但在你拖动时代码不再执行,也就是阻塞了,当你不再控制窗体时会继续执行,其实这还是一个单线程
- for (int i = ; i < ; i++)
- {
- for (int j = ; j < ; j++)
- {
- textBox1.Text = i.ToString() + " " + j.ToString();
- Application.DoEvents();
- }
- }
方法2:多线程
2.1:取消控件跨线程检测(不推荐有时会出现一些莫名奇妙的错误如控件不能加载等问题)
2.1.1取消窗体内控件的跨线程检查(单个控件取消也可以)
- public Form1()
- {
- InitializeComponent();
- CheckForIllegalCrossThreadCalls = false;//干掉检测 不再检测跨线程
- }
2.1.2新建线程实现跨线程访问
- /// <summary>
- /// 新建线程并执行
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void button1_Click(object sender, EventArgs e)
- {
- ThreadStart thStart = new ThreadStart(Pro);//threadStart委托
- Thread thread = new Thread(thStart);
- thread.Priority = ThreadPriority.Highest;
- thread.IsBackground = true; //关闭窗体继续执行
- thread.Start();
- }
- public void Pro()
- {
- for (int i = ; i < ; i++)
- {
- for (int j = ; j < ; j++)
- {
- textBox1.Text = j.ToString();
- }
- }
- }
2.2:主线程中操作(推荐)
2.2.1 不用取消跨线程访问
- /// <summary>
- /// 新建线程并执行
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void button1_Click(object sender, EventArgs e)
- {
- ThreadStart thStart = new ThreadStart(Pro);//threadStart委托
- Thread thread = new Thread(thStart);
- thread.Priority = ThreadPriority.Highest;
- thread.IsBackground = true; //关闭窗体继续执行
- thread.Start();
- }
- public void Pro()
- {
- for (int i = ; i < ; i++)
- {
- for (int j = ; j < ; j++)
- {
- if (textBox1.InvokeRequired)//不同线程访问了
- textBox1.Invoke(new Action<TextBox, string>(SetTxtValue), textBox1, j.ToString());//跨线程了
- else//同线程直接赋值
- textBox1.Text = j.ToString();
- }
- }
- }
- private void SetTxtValue(TextBox txt, string value)
- {
- txt.Text = value;
- }
注:多个线程同时访问一个方法时 需要锁定
- public static readonly object obj = new object();
- public void Pro()
- {
- //lock(obj){}=Monitor.Enter(obj) Monitor.Exit(obj)
- lock (obj)
- {
- for (int i = ; i < ; i++)
- {
- for (int j = ; j < ; j++)
- {
- if (textBox1.InvokeRequired)//不同线程访问了
- textBox1.Invoke(new Action<TextBox, string>(SetTxtValue),
textBox1, j.ToString());//跨线程了- else//同线程直接赋值
- textBox1.Text = j.ToString();
- }
- }
- }
- }
3.窗体与自定义类之间的多线程操作(适用数据量大查询速度慢时 让数据在新线程中查询 防主线程卡死)
3.1自定义类中定义事件,并定义各事件执行的步骤方法
3.2窗体中实现类,并生成类各事件,在多线程中执行自定义类的步骤方法
3.3 代码3.1
- public class WeiTuo
- {
- public int count { get; set; }
- public event EventHandler StartEvent;
- public event EventHandler MidEvent;
- public event EventHandler EndEvent;
- public event EventHandler EEvent;
- public void ExecEvent()
- {
- try
- {
- using (SqlConnection con = new SqlConnection("server=.;uid=sa;pwd=123;database=oa"))
- {
- using (SqlDataAdapter adp = new SqlDataAdapter("select * from a", con))
- {
- DataTable dt = new DataTable();
- adp.Fill(dt);
- StartEvent(dt.Rows.Count, null);
- for (int i = ; i < dt.Rows.Count; i++)
- {
- a ai = new a() {
- ID = (int)dt.Rows[i]["id"],
- Code = dt.Rows[i]["cCode"].ToString()
- } ;
- MidEvent(ai, null);
- }
- EndEvent(dt.Rows.Count, null);
- }
- }
- }
- catch (Exception e)
- {
- EEvent(e.Message, null);
- }
- }
- }
- public class a
- {
- public int ID { get; set; }
- public String Code { get; set; } = "";
- }
3.4 代码3.2
- private void button6_Click(object sender, EventArgs e)
- {
- WeiTuo wt = new WeiTuo();
- wt.StartEvent += Wt_StartEvent;
- wt.MidEvent += Wt_MidEvent;
- wt.EndEvent += Wt_EndEvent;
- wt.EEvent += Wt_EEvent;
- Thread th = new Thread(wt.ExecEvent);
- th.Start();
- }
- //特殊委托 action
- private void Wt_StartEvent(object sender, EventArgs e)
- {
- Action<string> setLVItem = (s) => { listView1.Items.Add(s); };
- this.Invoke(setLVItem, sender.ToString());
- }
- //特殊委托 action
- private void Wt_MidEvent(object sender, EventArgs e)
- {
- Action<string> setLVItem = (s) => { listView1.Items.Add(s); };
- this.Invoke(setLVItem, ((a)sender).Code);
- }
- #region 委托实现
- private void Wt_EndEvent(object sender, EventArgs e)
- {
- this.Invoke(new setLVItem(setEndValue), "成功");
- }
- delegate void setLVItem(string s);
- void setEndValue(string s)
- {
- MessageBox.Show(s);
- }
- #endregion
- private void Wt_EEvent(object sender, EventArgs e)
- {
- Action<string> ShowBox = (s) => { MessageBox.Show(s); };
- this.Invoke(ShowBox, sender.ToString());
- }
3.5 结果如下图
task任务与thread大同小异
使用时 尽量少的让控件跨线程 可通过ref 或 out 对参数传出 检测线程结束 再给控件赋值
也可用task的wait方法
4 异步回调
- private void button1_Click(object sender, EventArgs e)
- {
- Func<int, int, int> Sum = (i, j) =>
- {
- Thread.Sleep();
- return i + j;
- };
- listView1.Items.Add("开始");
- IAsyncResult iar = Sum.BeginInvoke(, , CallbackWhenDone, "我是测试");
- listView1.Items.Add("over");
- }
- private void CallbackWhenDone(IAsyncResult iar)
- {
- AsyncResult ar = (AsyncResult)iar;
- Func<int, int, int> f = (Func<int, int, int>)ar.AsyncDelegate;
- Action<ListView> a = (lv) =>
- {
- lv.Items.Add(ar.AsyncState.ToString());
- lv.Items.Add(f.EndInvoke(iar).ToString());
- };
- this.Invoke( a,listView1);
- }
c# Winform 多线程操作的更多相关文章
- C# winform编程中多线程操作控件方法
private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...
- 浅述WinForm多线程编程与Control.Invoke的应用
VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...
- C#多线程操作界面控件的解决方案(转)
C#中利用委托实现多线程跨线程操作 - 张小鱼 2010-10-22 08:38 在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了 ...
- WinForm多线程学习文档
基础篇 怎样创建一个线程 受托管的线程与 Windows线程 前台线程与后台线程 名为BeginXXX和EndXXX的方法是做什么用的 异步和多线程有什么关联 WinForm多线程编程篇 我的多线程W ...
- WinForm多线程实现HTTP网络检测工具
一.背景描述与课程介绍 明人不说暗话,跟着阿笨一起玩WinForm.本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高 ...
- WinForm多线程编程与Control.Invoke的应用浅谈
在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在WinForm开发中必不可 ...
- 【转】浅述WinForm多线程编程与Control.Invoke的应用
环境:VS2008.C#3.0 在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的 ...
- C#中级-常用多线程操作(持续更新)
一.前言 多线程操作一直是编程的常用操作,掌握好基本的操作可以让程序运行的更加有效.本文不求大而全,只是将我自己工作中常常用到的多线程操作做个分类和总结.平时记性不好的时候还能看看.本文参 ...
- java多线程操作
进程是程序的一次动态的执行过程,它经历了从代码加载.执行完毕的一个完整过程,这个过程也是进程本身从产生.发展到最终消亡的过程. 多线程是实现并发机制的一种有效的手段.进程和线程一样,都是实现并发的一个 ...
随机推荐
- upc组队赛12 Janitor Troubles【求最大四边形面积】
Janitor Troubles Problem Description While working a night shift at the university as a janitor, you ...
- 通用唯一标识码UUID的介绍及使用。
什么是UUID? UUID全称:Universally Unique Identifier,即通用唯一识别码. UUID是由一组32位数的16进制数字所构成,是故UUID理论上的总数为16^32 = ...
- 热修复设计之CLASS_ISPREVERIFIED(二)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680本篇文章将继续从CLASS_ISPREVERIFIED实战来介绍热 ...
- Manjaro配置中国源
1.自动寻找中国源 sudo pacman-mirrors -i -c China -m rank//更新镜像排名sudo vim /etc/pacman.d/mirrorlist //查看选择的源s ...
- Java连接ActiveMQ代码示例(Producer和Consumer)
import org.apache.activemq.ActiveMQConnection; import org.apache.activemq.ActiveMQConnectionFactory; ...
- SpringMVC整合Freemarker(含Demo源码)(转)
转自:http://blog.csdn.net/sinat_27535209/article/details/61199452 整合过程如下: 1.新建一个maven web工程,使用maven依赖s ...
- vue之全局自定义组件
在项目开发中,往往需要使用到一些公共组件,比如,弹出消息.面包屑或者其它的组件,为了使用方便,将其以插件的形式融入到vue中,以面包屑插件为例: 1.创建公共组件MyBread.vue <tem ...
- 【转】前后端分离架构:web实现前后端分离,前后端解耦
一.前言 ”前后端分离“已经成为互联网项目开发的业界标杆,通过Tomcat+Ngnix(也可以中间有个Node.js),有效地进行解耦.并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务架构 ...
- Mate Translate的特色功能phrasebook 常用语手册介绍
Mate Translate是Mac os系统上一款多国语言即时翻译工具,支持103种语言之间的即时互译,还可以在你的所有设备之间轻松同步.Mate Translate 不但推出了适应各个平台使用的客 ...
- 分享linux中导入sql文件的方法
为使用阿里云主机,没有装ftp,也没有装phpmyadmin,所以一切都得靠命令行.转移网站的重要一步就是转移数据库,这里简单介绍一下如何在这种情况下导入sql文件 因导出sql文件 在你原来的网站服 ...