c# delegate(委托)与多线程

TOR下载和网桥配置教程 阅读详情

 

前些天写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();
uniapp 记录运动轨迹 开发_智能手环穿戴设备APP开发解决方案 智能手环是一种穿戴式智能设备,是目前备受关注的科技产品。目前智能手环具有的功能有记录日常生活中的运动数据、移动轨迹,定位等,有些还可以进行睡眠质量的检测,并将这些数据传送至移动端如手机、平板等,可对数据进行分析,指导健康生活的作用。而智能手环开发方案就是将这些功能实现,将算法烧录到主控板上。智能手环都有哪些功能  1、记录运动数据  对于喜欢健身的用户来说,智能手环记录的运动数据功能... 阅读详情

相关推荐

C#中实现多线程委托的具体指南

本文还有配套的精品资源,点击获取 简介:在C#编程中,多线程委托是提高应用程序性能和响应性的关键概念。本文将介绍如何在Windows Forms应用中利用这些概念,以按钮点击事件为例,通过主线程和新建线程分别向listview控件添加数据。内容涵盖线程创建管理、委托的使用、事件和异步操作,以及如何安全地从多线程中更新UI控件。 1. 多线程概念C#实现 ...

weixin_42513870的博客 922

c# 委托多线程

很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并启动一个新的线程。public void ThreadProc();Thread thread = new Thread( new ThreadStart( ThreadProc ) );thread.IsBackground = true;thread.Start();但是很多时候,在新的线程中,我

贝吉塔的专栏 9316

Python基于Django图书管理系统源码(95分以上大作业项目).zip

Python基于Django图书管理系统源码(95分以上大作业项目).zip 已获导师指导并通过的高分项目,也可作为期末大作业和课程设计,纯手打高分项目,代码完整下载可用,小白也可实战。Python基于Django图书管理系统源码(95分以上大作业项目).zip 已获导师指导并通过的高分项目,也可作为期末大作业和课程设计,纯手打高分项目,代码完整下载可用,小白也可实战。Python基于Django图书管理系统源码(95分以上大作业项目).zip 已获导师指导并通过的高分项目,也可作为期末大作业和课程设计,纯手打高分项目,代码完整下载可用,小白也可实战。Python基于Django图书管理系统源码(95分以上大作业项目).zip 已获导师指导并通过的高分项目,也可作为期末大作业和课程设计,纯手打高分项目,代码完整下载可用,小白也可实战。Python基于Django图书管理系统源码(95分以上大作业项目).zip 已获导师指导并通过的高分项目,也可作为期末大作业和课程设计,纯手打高分项目,代码完整下载可用,小白也可实战。Python基于Django图书管理系统源码(95分以

C#高级--多线程详解

C#高级–多线程详解 零、文章目录 一、什么是多线程 1、进程 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。 而一个进程又是由多个线程所组成的。 2、线程 线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。 3、句柄 句柄是Windows系统中对象或实例的标识,这些对象包括模块、应用程序实例、窗口、控制、位图、GDI对象、资源、文件等。 4、多线程 (1)多线程概念 多线程是指程序中

李宥的博客 5万+

c#多线程委托的使用

一、基本概念 先说什么是进程 1、进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程...

qq_39559182的博客 1854

c#多线程委托

一:线程 在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。 不带参数的启动方式  如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread:  带参数的启动方法 带参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和Thr

文少-笨小孩 1万+

c# 委托实现多线程的实例

前面学习了委托,事件和多线程相关的知识。今天我们就通过在项目中常见的实例来加深对多线程的应用。 一、使用线程在窗体中显示进度条 在Winform应用程序中,经常用进度条显示进度信息。这时候就可能用到多线程。如果不采用多线程控制进度条的话,窗口界面很容易假死(无法看到进度信息,看起来像界面卡住了)。 在这个实例中,我们建立一个窗体,窗体中包括一个后台组件,一个进度条控件。当在主窗体中按“开始”...

u014677855的博客 1万+

C# Delegate(委托)多线程

C# Delegate(委托)多线程 很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并启动一个新的线程。public void ThreadProc();Thread thread = new Thread(new ThreadStart(ThreadProc));thread.IsBackground = true;...

T87406621的博客 166

C# Delegate/委托 多线程

转自http://www.imwls.com/c-delegate-threading/,感觉这篇文章写的很好,拿来分享一下,呵呵 最近写到两个程序都用到了多线程,但是由于需要调用主线程UI,所以总是会出错,Google了一下,终于找到了使用Delegate(委托)的解决方法,现在贴出来存档并且分享:    很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并

小安屋 908

C#多线程界面操作c# delegate(委托)多线程窗体传值

c# delegate(委托)多线程 很多时候写windows程序都需要结合多线程,在.net中用如下得代码来创建并启动一个新的线程。 public void ThreadProc(); Thread thread = new Thread( new ThreadStart( ThreadProc ) ); thread.IsBackground = true; thread.St...

果冻村长 1217

C#网络编程----(三)委托多线程

要求: 1、 定义并使用委托实现如下输出: Morning, Jimmy Zhang 早上好, 张子阳 2、 分别通过以下三种方式将信息添加到窗口中。 第一种方式:直接向textBlock中添加信息 第二种方式:通过调用方法向textBlock中添加信息 第三种方式:通过多线程...

1900的博客 803

多线程(一)——委托多线程

委托多线程

静心学习,开心生活 1611

c#委托多线程的实质

delegate委托)的概念,.Net的委托本质上就是指向函数的指针,只不过这种指针是经过封装后类型安全的。委托和线程是两个不同的概念,线程是动态的,委托就是一个或一组内存地址,是静态的。线程执行时如果遇到了指向函数的指针就执行这个函数。.Net为了方便编程,给委托赋予了两种方式以供调用线程来执行,即同步和异步方式,它们分别通过Invoke和BeginInvoke来开启。Invoke就是同步执行

u010613052的博客 1631

C# Delegate(委托)多线程 (转载不易)

以前VC中创建一个新的线程需要调用AfxBeginThread函数,该函数中第一个参数就是线程函数的地址,而第二个参数是一个类型为LPVOID的指针类型,这个参数将传递给线程函数。我们需要将传递给线程的参数和线程函数包装成一个单独的类,然后在这个类的构造函数中初始化该线程所需的参数,然后再将该实例的线程函数传递给Thread类的构造函数。BeginInvoke 生成异步方法调用。//-----------------------以下为自己写的异步委托的例子------------------------

weixin_42609581的博客 778
上一篇: C++初学者必看(转)
下一篇: C#文件处理机制总结
fairy_study
博客等级 码龄18年 29粉丝 35原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值