前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C#多线程

C#多线程

作者头像
aehyok
发布于 2018-09-11 04:31:27
发布于 2018-09-11 04:31:27
58800
代码可运行
举报
文章被收录于专栏:技术博客技术博客
运行总次数:0
代码可运行

前言

根据上一节中https://cloud.tencent.com/developer/article/1395149对多线程的入门了解。本节就来探讨一下简单的使用多线程。

使用多线程  

线程用Thread类来创建, 通过ThreadStart委托来指明方法从哪里开始运行,下面是ThreadStart委托如何定义的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public delegate void ThreadStart();

调用Start方法后,线程开始运行,线程一直到它所调用的方法返回后结束。下面是一个例子,使用了C#的语法创建TheadStart委托:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    class Program
    {
        static void Main(string[] args)
        {
            System.Threading.Thread thread = new System.Threading.Thread(Go);
            thread.Start();
            Go();
            Console.ReadLine();

        }

        static void Go() { Console.WriteLine("hello!"); }
    }

在这个例子中,线程t执行Go()方法,大约与此同时主线程也调用了Go(),结果是两个几乎同时hello被打印出来:

一个线程可以通过C#堆委托简短的语法更便利地创建出来:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
              System.Threading.Thread t = new System.Threading.Thread (delegate() { Console.WriteLine ("Hello!"); });
              t.Start();

线程有一个IsAlive属性,在调用Start()之后直到线程结束之前一直为true。一个线程一旦结束便不能重新开始了。

将数据传入ThreadStart中

 话又说回来,在上面的例子里,我们想更好地区分开每个线程的输出结果,让其中一个线程输出大写字母。我们传入一个状态字到Go中来完成整个任务,但我们不能使用ThreadStart委托,因为它不接受参数,所幸的是,.NET framework定义了另一个版本的委托叫做ParameterizedThreadStart, 它可以接收一个单独的object类型参数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
namespace System.Threading
{
    // 摘要:
    //     表示在 System.Threading.Thread 上执行的方法。
    //
    // 参数:
    //   obj:
    //     包含该线程过程的数据的对象。
    [ComVisible(false)]
    public delegate void ParameterizedThreadStart(object obj);
}

示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        static void Main(string[] args)
        {
            System.Threading.Thread thread = new System.Threading.Thread(Go);
            thread.Start(true); 
            Go(false);
            Console.ReadLine();
        }

        static void Go(object upperCase)
        {
            bool upper = (bool)upperCase;
            Console.WriteLine(upper ? "HELLO!" : "hello!");
        }

在整个例子中,编译器自动推断出ParameterizedThreadStart委托,因为Go方法接收一个单独的object参数,就像这样写:在整个例子中,编译器自动推断出ParameterizedThreadStart委托,因为Go方法接收一个单独的object参数,就像这样写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            System.Threading.Thread thread = new System.Threading.Thread(Go);
            thread.Start(true); 

ParameterizedThreadStart的特性是在使用之前我们必需对我们想要的类型(这里是bool)进行装箱操作,并且它只能接收一个参数。

  一个替代方案是使用一个匿名方法调用一个普通的方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    class Program
    {
        static void Main()
        {
            System.Threading.Thread t = new System.Threading.Thread(delegate() { WriteText("Hello"); });
            t.Start();
            Console.ReadLine();
        }
        static void WriteText(string text) { Console.WriteLine(text); }
    }

优点是目标方法(这里是WriteText),可以接收任意数量的参数,并且没有装箱操作。不过这需要将一个外部变量放入到匿名方法中,像下面的一样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    class Program
    {
        static void Main()
        {
            string text = "Before";
            System.Threading.Thread t = new System.Threading.Thread(delegate() { WriteText(text); });
            text = "aehyok";
            t.Start();
            Console.ReadLine();
        }
        static void WriteText(string text) { Console.WriteLine(text); }
    }

匿名方法打开了一种怪异的现象,当外部变量被后来的部分修改了值的时候,可能会透过外部变量进行无意的互动。有意的互动(通常通过字段)被认为是足够了!一旦线程开始运行了,外部变量最好被处理成只读的——除非有人愿意使用适当的锁。

另一种较常见的方式是将对象实例的方法而不是静态方法传入到线程中,对象实例的属性可以告诉线程要做什么,如下列重写了原来的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    class Program
    {
        bool upper;
        static void Main()
        {
            Program instance1 = new Program();

            instance1.upper = true;

            System.Threading.Thread t = new System.Threading.Thread(instance1.Go);
            t.Start();
            Program instance2 = new Program();
            instance2.Go();
            Console.ReadLine();
        }
        void Go() { Console.WriteLine(upper ? "HELLO!" : "hello!"); }
    }

命名线程

  线程可以通过它的Name属性进行命名,这非产有利于调试:可以用Console.WriteLine打印出线程的名字,Microsoft Visual Studio可以将线程的名字显示在调试工具栏的位置上。线程的名字可以在被任何时间设置——但只能设置一次,重命名会引发异常。

  程序的主线程也可以被命名,下面例子里主线程通过CurrentThread命名:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        static void Main()
        {
            System.Threading.Thread.CurrentThread.Name = "main";
            System.Threading.Thread worker = new System.Threading.Thread(Go);
            worker.Name = "worker";
            worker.Start();
            Go();
            Console.ReadLine();
        }

        static void Go()
        {

            Console.WriteLine("Hello from " + System.Threading.Thread.CurrentThread.Name);

        }

还有几点下节继续。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2013-05-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C# 给多线程传参的三种方式
从《C#高级编程》了解到给线程传递参数有两种方式,一种方式是使用带ParameterizedThreadStart委托参数的Thread构造函数,另一种方式是创建一个自定义类,把线程的方法定义为实例的方法,这样就可以初始化实例的数据,之后启动线程。
vv彭
2021/02/02
3.3K0
干货分享:详解线程的开始和创建
代码下载 Thread_博客园_cnblogs_jackson0714.zip 第一篇~第三篇的代码示例: 源码地址:https://github.com/Jackson0714/Threads 一、
悟空聊架构
2018/05/18
6500
C#基础知识回顾--线程传参
  在不传递参数情况下,一般大家都使用ThreadStart代理来连接执行函数,ThreadStart委托接收的函数不能有参数, 也不能有返回值。如果希望传递参数给执行函数,则可以使用带参数的ParameterizedThreadStart委托, public delegate void ParameterizedThreadStart(Object obj) 可以将要传送给线程函数的信息封装为一个对象,然后调用Thread类的以下构造函数  public Thread (Parameterized
hbbliyong
2018/03/05
8860
C# 多线程详细讲解「建议收藏」
进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。
全栈程序员站长
2022/11/01
2.2K0
异步与多线程——c#
异步这概念刚开始接触的时候,不是那么容易接受,但是需要用的地方还真的挺多的,刚学习的时候,也很懵逼走了不少弯路,所以这里有必要总结一下。 msdn文档:https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/ 官方的简介: *.NET Framework提供了执行异步操作的三种模式: 异步编程模型(APM)模式(也称为IAsyncResult的模式),其中异步操作要求Begin和End方法(例如,BeginWrite和EndWrite异步写入操作)。这种模式不再被推荐用于新开发。有关更多信息,请参阅异步编程模型(APM)。
vv彭
2021/01/07
1.8K0
异步与多线程——c#
C#多线程委托ParameterizedThreadStart应用
C#使用线程时首先需要创建线程,使用Thread类构造函数创建实例需要用到ThreadStart委托或者ParameterizedThreadStart 委托创建 Thread 类的实例,ThreadStart 委托只能用于无返回值、无参数的方法,ParameterizedThreadStart 委托则可以用于带参数的方法。线程不会直接运行,直至调用Start()方法时为止。
zls365
2020/08/19
1.6K0
C#多线程委托ParameterizedThreadStart应用
c#之线程基础(一)
在上面的代码中,步骤4定义了方法 PrintNumber , 该方法会被主线程和新创建的线程使用。
Vincent-yuan
2019/10/23
4640
c#之线程总结(一)
在我们做项目的时候会经常用到线程,但线程也不是万能的,用线程需要注意的东西也很多,自己做了一下总结 这次总结主要说三个部分 1 线程之委托方法 2 给线程传参 3 三种方法控制线程同步 我们先看一下小例子: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadMethod { class Progr
lpxxn
2018/01/31
4760
c#之线程总结(一)
C#多线程同步事件及等待句柄
最近捣鼓了一下多线程的同步问题,发现其实C#关于多线程同步事件处理还是很灵活,这里主要写一下,自己测试的一些代码,涉及到了AutoResetEvent 和 ManualResetEvent,当然还有也简要提了一下System.Threading.WaitHandle.WaitOne 、System.Threading.WaitHandle.WaitAny和System.Threading.WaitHandle.WaitAll ,下面我们一最初学者的角度来看,多线程之间的同步。
全栈程序员站长
2022/09/14
1.3K0
编写高质量代码改善C#程序的157个建议[为泛型指定初始值、使用委托声明、使用Lambda替代方法和匿名方法]
  泛型并不是C#语言一开始就带有的特性,而是在FCL2.0之后实现的新功能。基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全。委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊,它是对方法的引用。事件本身也是委托,它是委托组,C#中提供了关键字event来对事件进行特别区分。一旦我们开始编写稍微复杂的C#代码,就肯定离不开泛型、委托和事件。本章将针对这三个方面进行说明。
aehyok
2018/08/31
4860
编写高质量代码改善C#程序的157个建议[为泛型指定初始值、使用委托声明、使用Lambda替代方法和匿名方法]
C#多线程系列(1):Thread
本篇是《多线程入门和实践(初级)》的第一篇,也是大家相当熟悉和不屑的的最简单的入门部分。作为系列文章,笔者将从最简单的部分开始,与各位伙伴一起不断学习和探究 C# 中的多线程。
痴者工良
2021/04/26
1.5K0
多线程编程01
线程可以被描述为它所处的进程中的一个微进程,它拥有起点,执行的顺序系列和一个终点。
Echo_Wish
2023/11/30
1870
C# 多线程 ThreadStart和ParameterizedThreadStart
线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率。每个线程都定义了一个独特的控制流。如果应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。
全栈程序员站长
2022/09/14
5880
C#线程入门
 C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。
aehyok
2018/09/11
5490
C#线程入门
C#学习笔记——线程传参
如果使用了ParameterizedThreadStart委托,线程的入口必须有一个object类型的参数,且返回类型为void。且看下面的例子:
vv彭
2021/09/07
5160
.NET面试题系列[17] - 多线程概念(2)
当我们创建了一个线程后,线程里面主要包括线程内核对象、线程环境块、1M大小的用户模式栈和内核模式栈。
s055523
2018/09/14
1.4K0
.NET面试题系列[17] - 多线程概念(2)
[C#]多线程定时器
System.Threading.Timer是最简单的多线程定时器:它只有一个构造器和两个方法(尤其适合于像作者这样的极简主义者!)。在接下来的例子中,定时器会在第一个五秒钟结束后调用Tick方法,并输出“tick…”。而后每一秒钟调用一次Tick方法,直至用户按下回车键:
科控物联
2022/03/29
1.1K0
[C#]多线程定时器
C# 多线程编程 ThreadStart ParameterizedThreadStart
在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。      不带参数的启动方式      如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:
全栈程序员站长
2022/09/14
5020
谈谈C#中各种线程的使用及注意项~
接下来我们就来学习一下 timer 吧,摇摇脑袋,清醒一下,接下来开始学习....
用户7053485
2020/06/19
2K0
C#多线程学习一
一、概述:C#支持多线程并行执行程序,一个线程有他单独的执行路径,能够与其他线程同时执行,一个程序是由一个单线程开始,该单线程由CLR(公共语言运行时)和操作系统创建而成,并具有多线程创建额外线程的功能。 1、创建线程的方法 <1>、通过Thread类来创建线程,ThreadStart委托创建线程从哪里开始运行的方法 using System; using System.Threading; namespace Mulithreading{ class CreateThreadMethods{
郑小超.
2018/01/24
1.1K0
C#多线程学习一
相关推荐
C# 给多线程传参的三种方式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验