C# 委托 多线程
C#委托和多线程[转载]
很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并启动一个新的线程。
public void ThreadProc();
Thread thread = new Thread( new ThreadStart( ThreadProc ) );
thread.IsBackground = true;
thread.Start();
但是很多时候,在新的线程中,我们需要与UI进行交互,在.net中不允许我们直接这样做。可以参考MSDN中的描述:
“Windows 窗体”使用单线程单元 (STA) 模型,因为“Windows 窗体”基于本机 Win32 窗口,而 Win32 窗口从本质上而言是单元线程。STA 模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。除了 Windows 窗体之外,.NET Framework 中的类使用自由线程模型。
STA 模型要求需从控件的非创建线程调用的控件上的任何方法必须被封送到(在其上执行)该控件的创建线程。基类 Control 为此目的提供了若干方法(Invoke、BeginInvoke 和 EndInvoke)。Invoke 生成同步方法调用;BeginInvoke 生成异步方法调用。
Windows 窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一个线程调用控件的方法,那么必须使用控件的一个 Invoke 方法来将调用封送到适当的线程。
正如所看到的,我们必须调用Invoke方法,而BeginInvoke可以认为是Invoke的异步版本。调用方法如下:
public delegate void OutDelegate(string text);
public void OutText(string text)
{
txt.AppendText(text);
txt.AppendText( "\t\n" );
}
OutDelegate outdelegate = new OutDelegate( OutText );
this.BeginInvoke(outdelegate, new object[]{text});
如果我们需要在另外一个线程里面对UI进行操作,我们需要一个类似OutText的函数,还需要一个该函数的委托delegate,当然,这里展示的是自定义的,.net中还有很多其他类型的委托,可以直接使用,不需要而外声明。例如:MethodInvoker和EventHandler,这两种类型委托的函数外观是固定的,MethodInvoker是void Function()类型的委托,而EventHandler是void Function(object, EventArgs)类型的委托,第一个不支持参数,第二中的参数类型和数量都是固定的,这两种委托可以很方便的调用,但是缺乏灵活性。请注意BeginInvoke前面的对象是this,也就是主线程。现在再介绍Control.InvokeRequired,Control是所有控件的基类,对于这个属性MSDN的描述是:
获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
该属性可用于确定是否必须调用 Invoke 方法,当不知道什么线程拥有控件时这很有用。
也就是说通过判断InvokeRequired可以知道是否需要用委托来调用当前控件的一些方法,如此可以把OutText函数修改一下:
public delegate void OutDelegate(string text);
public void OutText(string text)
{
if( txt.InvokeRequired )
{
OutDelegate outdelegate = new OutDelegate( OutText );
this.BeginInvoke(outdelegate, new object[]{text});
return;
}
txt.AppendText(text);
txt.AppendText( "\t\n" );
}
注意,这里的函数没有返回,如果有返回,需要调用Invoke或者EndInvoke来获得返回的结果,不要因为包装而丢失了返回值。如果调用没有完成,Invoke和EndInvoke都将会引起阻塞。
现在如果我有一个线程函数如下:
public void ThreadProc()
{
for(int i = 0; i < 5; i++)
{
OutText( i.ToString() );
Thread.Sleep(1000);
}
}
如果循环的次数很大,或者漏了Thread.Sleep(1000);,那么你的UI肯定会停止响应,想知道原因吗?看看BeginInvoke前面的对象,没错,就是this,也就是主线程,当你的主线程不停的调用OutText的时候,UI当然会停止响应。
与以前VC中创建一个新的线程需要调用AfxBeginThread函数,该函数中第一个参数就是线程函数的地址,而第二个参数是一个类型为LPVOID的指针类型,这个参数将传递给线程函数。现在我们没有办法再使用这种方法来传递参数了。我们需要将传递给线程的参数和线程函数包装成一个单独的类,然后在这个类的构造函数中初始化该线程所需的参数,然后再将该实例的线程函数传递给Thread类的构造函数。代码大致如下:
public class ProcClass
{
private string procParameter = "";
public ProcClass(string parameter)
{
procParameter = parameter;
}
public void ThreadProc()
{
}
}
ProcClass threadProc = new ProcClass("use thread class");
Thread thread = new Thread( new ThreadStart( threadProc.ThreadProc ) );
thread.IsBackground = true;
thread.Start();
就是这样,需要建立一个中间类来传递线程所需的参数。
那么如果我的线程又需要参数,又需要和UI进行交互的时候该怎么办呢?可以修改一下代码:
public class ProcClass
{
private string procParameter = "";
private Form1.OutDelegate delg = null;
public ProcClass(string parameter, Form1.OutDelegate delg)
{
procParameter = parameter;
this.delg = delg;
}
public void ThreadProc()
{
delg.BeginInvoke("use ProcClass.ThreadProc()", null, null);
}
}
ProcClass threadProc = new ProcClass("use thread class", new OutDelegate(OutText));
Thread thread = new Thread( new ThreadStart( threadProc.ThreadProc ) );
thread.IsBackground = true;
thread.Start();
这里只是我的一些理解,如果有什么错误或者不当的地方,欢迎指出。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lekelaier_msn/archive/2007/06/24/1664235.aspx
C# 委托 多线程的更多相关文章
- WinForm中 事件 委托 多线程的应用
WinForm中 事件 委托 多线程的应用[以一个下载进度条为例] 第一步:首先我们创建一个winfor的项目 第二步:我们建一个窗体在一个窗体里面 打开一个另外的窗体 另外的窗体有一个按钮 点击后就 ...
- WinForm中 事件 委托 多线程的应用【以一个下载进度条为例】
第一步:首先我们创建一个winfor的项目 第二步:我们建一个窗体 在一个窗体里面 打开一个另外的窗体 另外的窗体有一个按钮 点击后就开始下载 下载完成后 在注册窗体上面 显示下载完成(达到在一个窗体 ...
- 异步委托 多线程实现摇奖器 winform版
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- .net 委托多线程 实时更新界面
Thread thread = new Thread(() => { button2.Invoke(new EventHandler(delegate { button2.Enabled = t ...
- .net 多线程的使用(Thread)
上篇 net 同步异步 中篇 多线程的使用(Thread) 下篇 net 任务工厂实现异步多线程 Thread多线程概述 上一篇我们介绍了net 的同步与异步,我们异步演示的时候使用的是委托多线程来实 ...
- 利用WPF建立自己的3d gis软件(非axhost方式)(十二)SDK中的导航系统
原文:利用WPF建立自己的3d gis软件(非axhost方式)(十二)SDK中的导航系统 先下载SDK:https://pan.baidu.com/s/1M9kBS6ouUwLfrt0zV0bPew ...
- OSGI.NET插件方式开发你的应用
之前一直从事C# WEB开发.基本都是业务开发,性能优化. 体力活占比90%吧.模块真的很多很多,每次部署经常出先各种问题.发布经常加班. 今年开始接触winform 开发.发现C# 的事件 委托 ...
- 多线程、委托、Invoke解决winform界面卡死的问题,并带开关
一.知识点介绍 1,更新控件的内容,应该调用控件的Invoke方法. Invoke指: 在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托.该方法接收一个委托类型和委托的参数,因此需要定义 ...
- BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题
BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 原文:http://www.sufeinet.com/thread-3707-1-1.html 大家可以先看看我上 ...
随机推荐
- Bugku web web基础$_GET
web基础$_GET 打开网站后发现 $what=$_GET['what']; echo $what; if($what=='flag') echo 'flag{****}'; 根据这段话的意思是将w ...
- 微信小程序支付功能讲解
前言:虽然小程序做过很多,但是一直觉得微信支付功能很是神秘,现在终于有机会接触心里还是有点小激动的,经过一番折腾发现支付也不过如此,在此记录下支付功能的实现过程 小程序的官方文档介绍到发起微信支付即调 ...
- bootstrap-multiselect 设置单选无效(设置单选依然是复选框)
bootstrap-multiselect 的使用介绍:https://www.cnblogs.com/landeanfen/p/5013452.html bootstrap-multiselect ...
- 如何理解重载与重写——Overload vs Override/Overwrite
重载: 在同一个类中,拥有类似功能的同名方法之间的关系叫做重载. 重载的条件:1.具有相同方法名和类似功能: 2.参数的类型或者个数不同: 3.与返回值无关: 重写: 在子父类的继承关系中,子类继承父 ...
- 4.16中Montage的一些变化
用4.16版本跟着网上的几篇Montage教程(分别是对应4.6和4.8版本)做,遇到各种各样的问题,经过各种搜索和分析,最终终于搞定了. 4.16版的Montage和之前有了不小的变化,总结如下: ...
- [CSP-S模拟测试]:序列(构造)
题目描述 给定$N,A,B$,构造一个长度为$N$的排列,使得:$\bullet$排列长度为$N$:$\bullet$最长上升子序列长度为$A$:$\bullet$最长下降子序列长度为$B$.我们有$ ...
- 走进JavaWeb技术世界14:Mybatis入门
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- RabbitMQ + Springboot +“Hello Word”
https://www.rabbitmq.com/getstarted.html 官网文档 我们将呼叫我们的消息发布者(发送者)发送和我们的消息消费者(接收者) Recv.发布者将连接到RabbitM ...
- 北风设计模式课程---依赖倒置原则(Dependency Inversion Principle)
北风设计模式课程---依赖倒置原则(Dependency Inversion Principle) 一.总结 一句话总结: 面向对象技术的根基:依赖倒置原则(Dependency Inversion ...
- p2619 [国家集训队2]Tree I [wqs二分学习]
分析 https://www.cnblogs.com/CreeperLKF/p/9045491.html 反正这个博客看起来很nb就对了 但是不知道他在说啥 实际上wqs二分就是原来的值dp[x]表示 ...