C# 委托 线程 窗体假死
基础理论
控件的线程安全检测
Control的Invoke和BeginInvoke
- Control.Invoke,Control.BeginInvoke和delegate.Invoke,delegate.BeginInvoke是不同的。
- Control.Invoke中的委托方法,执行在主线程,也就是我们的UI线程。而Control.BeginInvoke从命名上来看虽然具有异步调用的特征(Begin),但也仍然执行在UI线程。
- 如果在UI线程中直接调用Invoke和BeginInvoke,数据量偏大时,依然会造成UI的假死。
体验BeginInvoke

privatevoid btn_Start_Click(object sender, EventArgs e)
{
// 储存UI线程的标识符
int curThreadID = Thread.CurrentThread.ManagedThreadId; new Thread((ThreadStart)delegate()
{
PrintThreadLog(curThreadID);
})
.Start();
} privatevoid PrintThreadLog(int mainThreadID)
{
// 当前线程的标识符
// A代码块
int asyncThreadID = Thread.CurrentThread.ManagedThreadId; // 输出当前线程的扼要信息,及与UI线程的引用比对结果
// B代码块
label1.BeginInvoke((MethodInvoker)delegate()
{
// 执行BeginInvoke内的方法的线程标识符
int curThreadID = Thread.CurrentThread.ManagedThreadId; label1.Text =string.Format("Async Thread ID:{0},Current Thread ID:{1},Is UI Thread:{2}",
asyncThreadID, curThreadID, curThreadID.Equals(mainThreadID));
}); // 挂起当前线程3秒,模拟耗时操作
// C代码块
Thread.Sleep(3000);
}

Control.BeginInvoke的真正含义
所以,msdn对Control.BeginInvoke给出了这样的解释:在创建控件的基础句柄所在线程上异步执行指定委托。
Control.Invoke、BeginInvoke与Windows消息
publicobject Invoke(Delegate method, paramsobject[] args)
{
using (new MultithreadSafeCallScope())
{
returnthis.FindMarshalingControl().MarshaledInvoke(this, method, args, true);
}
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
public IAsyncResult BeginInvoke(Delegate method, paramsobject[] args)
{
using (new MultithreadSafeCallScope())
{
return (IAsyncResult)this.FindMarshalingControl().MarshaledInvoke(this, method, args, false);
}
}
privateobject MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous)
if (!synchronous)
{
return entry;
}
if (!entry.IsCompleted)
{
this.WaitForWaitHandle(entry.AsyncWaitHandle);
}
Application.DoEvents
解决方案
尝试”无假死”

privatereadonlyint Max_Item_Count =10000; privatevoid button1_Click(object sender, EventArgs e)
{
new Thread((ThreadStart)(delegate()
{
for (int i =0; i < Max_Item_Count; i++)
{
// 此处警惕值类型装箱造成的"性能陷阱"
listView1.Invoke((MethodInvoker)delegate()
{
listView1.Items.Add(new ListViewItem(newstring[]
{ i.ToString(), string.Format("This is No.{0} item", i.ToString()) }));
});
};
}))
.Start();
}

问题分析
最终方案
- 新建Windows组件DBListView.cs,让它继承自ListView。
- 在控件中添加如下代码:
public DBListView()
{
// 打开控件的双缓冲
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
privatevoid button1_Click(object sender, EventArgs e)
{
new Thread((ThreadStart)(delegate()
{
for (int i =0; i < Max_Item_Count; i++)
{
// 此处警惕值类型装箱造成的"性能陷阱"
dbListView1.Invoke((MethodInvoker)delegate()
{
dbListView1.Items.Add(new ListViewItem(newstring[]
{ i.ToString(), string.Format("This is No.{0} item", i.ToString()) }));
});
};
}))
.Start();
}
C# 委托 线程 窗体假死的更多相关文章
- 谈.Net委托与线程——解决窗体假死
转自:http://www.cnblogs.com/smartls/archive/2011/04/08/2008981.html#2457370 引言 在之前的<创建无阻塞的异步调用> ...
- C# winform窗体假死
C# winform窗体假死 我们经常会遇到当执行一个比较大的函数时,窗体会出现假死的现象,给用户的体验不是很好,于是我们遇到了问题,那么就必须解决,我们该如何解决呢,首先在自己的脑里画个问号,接下 ...
- C# 解决窗体假死的状态
异步调用是CLR为开发者提供的一种重要的编程手段,它也是构建高性能.可伸缩应用程序的关键.在多核CPU越来越普及的今天,异步编程允许使用非常少的线程执行很多操作.我们通常使用异步完成许多计算型.IO型 ...
- C#避免WinForm窗体假死
WinForm窗体在使用过程中如果因为程序等待时间太久而导致窗体本身假死无法控制,会严重影响用户的体验,这种情况大多是UI线程被耗时长的代码操作占用所致,可以新开一个线程用来完成耗时长的操作,然后再将 ...
- WinForm多线程及委托防止界面假死
当有大量数据需要计算.显示在界面或者调用sleep函数时,容易导致界面卡死,可以采用多线程加委托的方法解决. using System; using System.Collections.Generi ...
- WinForm多线程+委托防止界面假死
当有大量数据需要计算.显示在界面或者调用sleep函数时,容易导致界面卡死,可以采用多线程加委托的方法解决 using System; using System.Collections.Generic ...
- c#解决窗体假死的一种方法
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_C ...
- C# Winform 窗体界面”假死”后台线程阻塞 解决办法–BeginInvoke
原文:C# Winform 窗体界面"假死"后台线程阻塞 解决办法–BeginInvoke 这个方法可以用在任何后台任务耗时较长,造成界面“假死”界面控件不更新的情况. 比如要要执 ...
- 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死
原文地址:https://www.cnblogs.com/wangchuang/archive/2013/02/20/2918858.html .c# Invoke和BeginInvoke 区别 Co ...
随机推荐
- Shell的简单介绍(一)
shell 的分类 Shell 类别 易学性 可移植性 编辑性 快捷性 Bourne Shell (sh) 容易 好 较差 较差 Korn Shell (ksh) 较难 较好 好 较好 Bourne ...
- Codeforces Round #579 (Div. 3) 套题 题解
A. Circle of Students 题目:https://codeforces.com/contest/1203/problem/A 题意:一堆人坐成一个环,问能否按逆时针或者顺时针 ...
- Leetcode 9. Palindrome Number(水)
9. Palindrome Number Easy Determine whether an integer is a palindrome. An integer is a palindrome w ...
- IDEA设置Ctrl+滚轮调整字体大小
IDEA设置Ctrl+滚轮调整字体大小(转载) 按Ctrl+Shift+A,出现搜索框 输入mouse: 点击打开这个设置:勾选 点击ok,之后就可以通过Ctrl+滚轮 调整字体大小了.
- First-order logic
w https://en.wikipedia.org/wiki/First-order_logic
- vue 的sync用法
这个关键字在v2.3.0+ 新增,注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的).说白了 ...
- KindEditor上传图片一直提示undefined
图片已经上传成功了,但是就是不在文本编辑器里显示图片,一直弹出undefined 返回的JSON都对呀!这是官网说的返回值: //成功时 { "error" : 0, " ...
- 用Vue来实现音乐播放器(十八):右侧快速入口点击高亮
问题一:当我们点击右侧快速入口的时候 被点击的地方高亮 首先我们要知道右侧快速入口是为什么高亮??因为当watch()监控到scrollY的变化了的时候 将scrollY的值和listHeight ...
- uni-app学习资料整理-1.白话uni-app
白话uni-app https://ask.dcloud.net.cn/article/35657 文件内代码架构的变化 以前一个html大节点,里面有script和style节点: 现在templ ...
- 《图解设计模式》读书笔记8-3 STATE模式
目录 State模式 示例程序 实现的功能 不使用&使用状态模式对比 示例程序的类图 代码 角色和类图 角色 类图 拓展思路 分而治之 依赖于状态的处理 谁来管理状态迁移 易于增加新状态 实例 ...