主要是对一个过程需要的时间很长执行时会出现界面假死的情况

方法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 多线程操作的更多相关文章

  1. C# winform编程中多线程操作控件方法

    private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...

  2. 浅述WinForm多线程编程与Control.Invoke的应用

    VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...

  3. C#多线程操作界面控件的解决方案(转)

    C#中利用委托实现多线程跨线程操作 - 张小鱼 2010-10-22 08:38 在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了 ...

  4. WinForm多线程学习文档

    基础篇 怎样创建一个线程 受托管的线程与 Windows线程 前台线程与后台线程 名为BeginXXX和EndXXX的方法是做什么用的 异步和多线程有什么关联 WinForm多线程编程篇 我的多线程W ...

  5. WinForm多线程实现HTTP网络检测工具

    一.背景描述与课程介绍 明人不说暗话,跟着阿笨一起玩WinForm.本次分享课程属于<C#高级编程实战技能开发宝典课程系列>中的一部分,阿笨后续会计划将实际项目中的一些比较实用的关于C#高 ...

  6. WinForm多线程编程与Control.Invoke的应用浅谈

    在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在WinForm开发中必不可 ...

  7. 【转】浅述WinForm多线程编程与Control.Invoke的应用

    环境:VS2008.C#3.0 在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的 ...

  8. C#中级-常用多线程操作(持续更新)

    一.前言       多线程操作一直是编程的常用操作,掌握好基本的操作可以让程序运行的更加有效.本文不求大而全,只是将我自己工作中常常用到的多线程操作做个分类和总结.平时记性不好的时候还能看看.本文参 ...

  9. java多线程操作

    进程是程序的一次动态的执行过程,它经历了从代码加载.执行完毕的一个完整过程,这个过程也是进程本身从产生.发展到最终消亡的过程. 多线程是实现并发机制的一种有效的手段.进程和线程一样,都是实现并发的一个 ...

随机推荐

  1. 如何用QTP录制鼠标右键点击事件

    QTP录制鼠标右键单击事件要通过模拟键盘操作来实现 Step 1,修改ReplayType为2,一般情况默认设置是1的.(1 – 使用浏览器事件运行鼠标操作. 2 – 使用鼠标运行鼠标操作)Setti ...

  2. Linux/x86-64 - setuid(0) & chmod ("/etc/passwd", 0777) & exit(0) - 63 byes

    /* Title: Linux/x86-64 - setuid(0) & chmod ("/etc/passwd", 0777) & exit(0) - 63 by ...

  3. byte为什么要与0xff

    面对带正负号的数,会采用符号扩展,如果原值是正数,则高位补上0:如果原值是负数,高位补1.二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.当前的计算机系统使用的基本上是二 ...

  4. http(python)

    1.client 1) httpie http -f POST example.org hello=World http POST http://192.168.200.251:55101/Api/C ...

  5. JS对象 屏幕分辨率的高和宽 window.screen 对象包含有关用户屏幕的信息。 1. screen.height 返回屏幕分辨率的高 2. screen.width 返回屏幕分辨率的宽

    屏幕分辨率的高和宽 window.screen 对象包含有关用户屏幕的信息. 1. screen.height 返回屏幕分辨率的高 2. screen.width 返回屏幕分辨率的宽 注意: 1.单位 ...

  6. [转载]MinGW安装过程

    本文转自https://blog.csdn.net/my_wade/article/details/46941645 MinGW安装过程 一. 下载 MinGW官网下载地址:http://source ...

  7. java中继承条件下构造方法的执行过程

    继承条件下构造方法的调用规则如下: 情况1:如果子类的构造方法中没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法.在这种 ...

  8. 初撩Django-RESTful-rest_framework视图函数

    rest_framework中的视图函数: View函数 APIView函数 APIView的子类 mixins函数 viewsets函数 1.View函数 2.APIView函数 3.APIView ...

  9. 转译es6原生原生对象及方法,如Object.assign,Object.keys等,及promise

    下面主要为兼容恶心的ie 1,首先引入‘babel-polyfill’,可写在webpack.dev.js的entry.vendors数组里面 2,在入口文件如app.js里面import 'babe ...

  10. Delphi中点击网页弹出的Alert对话框的确定按钮

    思路: 使用Windows API函数遍历窗口,查找指定标题的窗口,然后从该窗口查找确定按钮,向该按钮发送鼠标消息进行模拟点击.由于IE8由Alert弹出的网页对话框的标题是“来自网页的消息”,而IE ...