威尼斯人线上娱乐

【威尼斯人线上娱乐】多线程编制程序实战1,创制线程

17 4月 , 2019  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//创造线程
//两组范围为一-10的数字会随机交叉输出,表明PrintNumbers方法同时运转在主线程和另三个线程中
【威尼斯人线上娱乐】多线程编制程序实战1,创制线程。namespace Recipe1
{
class Program
{
static void Main(string[] args)
{
Thread th = new Thread(PrintNumbers);
th.Start();
PrintNumbers();
Console.ReadKey();
}
static void PrintNumbers()
{
Console.WriteLine(“Starting”);
for (int i = 1; i < 10; i++)
{
Console.WriteLine(i);
}
}
}
}

原文:

using System; using System.Threading; class Program { static void
Main(string[] args) { Console.WriteLine(“主线程开首”);
/*=========================================/ Thread
类拥用5个重载的构造函数,常用的一个吸收3个ThreadStart类型的参数 public
Thread ( ThreadStart start) ThreadStart是四个寄托,定义如下 public
delegate void ThreadStart()
/=========================================*/ Thread th = new Thread(new
ThreadStart(ThreadMethod)); //也可简写为new Thread(ThreadMethod);
th.Start(); //运转线程 for (char i = ‘a’; i < ‘k’; i++) {
Console.WriteLine(“主线程:{0}”, i); Thread.Sleep(十0); } th.Join();
//主线程等待支援线程结束 Console.WriteLine(“主线程甘休”);
Console.ReadKey(); } static void ThreadMethod() {
Console.WriteLine(“匡助线程初始…”); for (int i = 0; i < 10; i++) {
Console.WriteLine(“协助线程:{0}”, i); Thread.Sleep(200); }
Console.WriteLine(“协助线程甘休.”); } }

**本文为原创,如需转载,请注解笔者和出处,感谢!

 

运营结果:

**

引言

主线程开首
主线程:a
支持线程起初…
帮扶线程:0
主线程:b
主线程:c
帮忙线程:一
主线程:d
主线程:e
帮助线程:二
主线程:f
赞助线程:三
主线程:g
主线程:h
救助线程:四
主线程:i
主线程:j
协助线程:5
支援线程:六
扶植线程:7
帮扶线程:八
帮忙线程:玖
协理线程截止.
主线程结束

上一篇:C#线程类别讲座(一):BeginInvoke和EndInvoke方法

  随着双核、四核等多核处理器的松手,多核处理器或超线程单核处理器的微型Computer已很宽泛,基于多核处理的编制程序技能也初始受到程序员们广泛关怀。那其间1个重点的方面正是营造四线程应用程序(因为不选用拾2线程的话,开荒人士就不可能充足发挥多核处理器的强硬质量)。

1、            
Thread类的骨干用法

  本文针对的是营造基于单核Computer的四线程应用程序,目的在于介绍多线程相关的基本概念、内涵,以及哪些通过System.Threading命名空间的类、委托和BackgroundWorker组件等两种花招创设三十二线程应用程序。

通过System.Threading.Thread类能够初始新的线程,并在线程仓库中运作静态或实例方法。能够经过Thread类的的构造方法传递2个无参数,并且不重返值(再次来到void)的寄托(ThreadStart),这么些委托的定义如下:

  本文倘使能为刚接触八线程的情人起到投石问路的效能也就笑容可掬了。当然,本人才疏学浅,文中难免会有欠缺或错误的地点,恳请各位朋友多多引导。

[ComVisibleAttribute(true)]

  壹.明白多线程

public delegate void ThreadStart()

  大家司空见惯领悟的应用程序正是三个*.exe文件,当运行*.exe应用程序以往,系统会在内部存款和储蓄器中为该程序分配一定的长空,同时加载一些该程序所需的财富。其实那就能够叫做创立了三个历程,能够由此Windows任务管理器查看那些历程的连锁消息,如印象名称、用户名、内部存储器使用、PID(唯1的进度标示)等,如图下所示。

大家能够通过如下的主意来确立并运营2个线程。

    

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

  而线程则只是经过中的三个主题进行单元。1个应用程序往往唯有贰个先后入口,如:

namespace MyThread
{
    class Program
    {
        public static void myStaticThreadMethod()
        {
            Console.WriteLine(“myStaticThreadMethod”);
        }
        static void Main(string[] args)
        {
            Thread thread1 = new Thread(myStaticThreadMethod);
            thread一.Start();  // 只要采用Start方法,线程才会运作
        }
    }
}

  [STAThread]

    除了运转静态的秘籍,还是可以够在线程中运维实例方法,代码如下:

  static void Main()   //应用程序主入口点

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

  {

namespace MyThread
{
    class Program
    {
        public void myThreadMethod()
        {
            Console.WriteLine(“myThreadMethod”);
        }
        static void Main(string[] args)
        {
            Thread thread2 = new Thread(new Program().myThreadMethod);
            thread2.Start();
        }
    }
}

  Application.EnableVisualStyles();

   
即使读者的法子很简单,或出来某种指标,也足以透过匿名委托或Lambda表达式来为Thread的构造方法赋值,代码如下:

  Application.SetCompatibleTextRenderingDefault(false);

Thread thread3 = new Thread(delegate() { Console.WriteLine(“匿名委托”); });
thread3.Start();

  Application.Run(new MainForm());

Thread thread4 = new Thread(( ) => { Console.WriteLine(“Lambda表达式”); });
thread4.Start();

  }

    在那之中Lambda表达式前面包车型地铁(
)表示一贯不参数。

  进度会含有二个进来此入口的线程,我们称为主线程。个中,天性
[STAThread]
提示应用程序的暗许线程模型是单线程单元(相关消息可参看http://msdn.microsoft.com/en-us/library/system.stathreadattribute(VS.71).aspx.aspx))。只含有三个主线程的过程是线程安全的,也就是程序仅有一条职业线,唯有成功了前边的天职技术实行排在后边的义务。

    为了分歧区别的线程,还足感到Thread类的Name属性赋值,代码如下:

  然当在程序处理三个很耗费时间的任务,如输出八个大的文书或远程访问数据库等,此时的窗体分界面程序对用户来说基本像是没影响一样,菜单、开关等都用持续。因为窗体上控件的响应事件也是索要主线程来实践的,而主线程正忙着干任何的事,控件响应事件就只能排队等着主线程忙完了再实践。

Thread thread5 = new Thread(() => { Console.WriteLine(Thread.CurrentThread.Name); });
thread5.Name = “我的Lamdba”;
thread5.Start();

  为了制服单线程的那么些毛病,Win32API能够让主线程再创造其他的次线程,但随就是主线程依旧次线程都以进程中独立的奉行单元,能够同时访问共享的数额,那样就有了二十多线程那些定义。

    假若将地点thread1至thread5松开一同实践,由于系统对线程的调度区别,输出的结果是不定的,如图壹是壹种只怕的输出结果。

  相信到那,应该对多线程有个相比较感性的认识了。但笔者在那要晋升一下,基于单核Computer的10二线程其实只是操作系统施展的贰个障眼法而已(但那不会苦恼大家领悟创设多线程应用程序的思绪),他并不能够裁减落成有着职务的小时,有时反而还会因为运用过多的线程而减低质量、延长期。之所以这么,是因为对于单CPU来讲,在四个单位时间(也称时间片)内,只好实行贰个线程,即只可以干一件事。当多个线程的光阴片用完时,系统会将该线程挂起,下三个小时内再进行另1个线程,如此,CPU以时间片为距离在四个线程之间轮换实践运算(其实那里还与各样线程的优先级有关,等第高的会优先处理)。由于交替时间距离非常短,所以导致了壹一线程都在“同时”职业的假象;而只要线程数目过多,由于系统挂起线程时要记录线程当前的意况数据等,这样又势必会下跌程序的完全品质。但对于这一个,多核处理器就能从本质上(真正的同时工作)提升程序的试行效能。

威尼斯人线上娱乐 1

  二. 线程异步与线程同步

                                                                 图1

  从线程施行职责的点子上得以分为线程同步和线程异步。而为了便于精通,后边描述中用“同步线程”指代与线程同步相关的线程,同样,用“异步线程”表示与线程异步相关的线程。

二、
定义3个线程类

  线程异步正是消除类似后边提到的实行耗费时间任务时分界面控件无法动用的主题素材。如创制二个次线程去尤其奉行耗费时间的天职,而任何如分界面控件响应那样的任务交给另2个线程试行(往往由主线程试行)。那样,三个线程之间通过线程调度器长期(时间片)内的切换,就模拟出多个职责“同时”被执行的机能。

    大家得以将Thread类封装在一个MyThread类中,以使任何从MyThread承继的类都有着四线程技艺。MyThread类的代码如下:

  线程异步往往是因而创制多少个线程施行多个义务,八个职业线同时开工,类似多辆在大规模的公路上互动的小车还要发展,互不干扰(读者要精通,本质上并不曾“同时”,仅仅是操作系统玩的一个障眼法。但那些障眼法却对狠抓我们的次第与用户之间的互动、以及压实程序的友好性很有用,不是吗)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MyThread
{
   abstract class MyThread
    {
       Thread thread = null;

  在介绍线程同步在此之前,先介绍贰个与此紧凑相关的定义——并发难点。

       abstract public void run();    

  前边提到,线程都以单身的施行单元,可以访问共享的数据。也正是说,在三个负有四个次线程的程序中,各类线程都能够访问同2个共享的数码。再稍加思虑你会发现这么只怕会出难题:由于线程调度器会随随便便的挂起某1个线程(前面介绍的线程间的切换),所以当线程a对共享数据D的访问(修改、删除等操作)实现此前被挂起,而此时线程b又刚好去拜谒数据D,那么线程b访问的则是3个不平稳的数额。那样就会生出十三分不便觉察bug,由于是不管三七二⑩第一行当生的,发生的结果是不行预测的,那样样的bug也都很难再次出现和调节和测试。那便是出新难点。

        public void start()
        {
            if (thread == null)
                thread = new Thread(run);
            thread.Start();
        }
    }
}

  为了化解二十四线程共同访问多个共享财富(也称互斥访问)时发生的出现问题,线程同步就涌出了。线程同步的机理,简来讲之,便是防守八个线程同时做客有些共享的财富。做法非常粗大略,标识访问某共享能源的那部分代码,当程序运营到有号子的地方时,CL帕杰罗(具体是什么能够先不管,只要理解它能说了算就行)对各线程实行调节:借使已有线程在走访一财富,CL福睿斯就会将别的访问那1能源的线程挂起,直到前1线程停止对该能源的拜访。那样就保证了同暂时间惟有八个线程访问该财富。打个比方,就像是某财富位居只有一独廊桥相连的半壁江山上,假使要利用该财富,我们就得排队,2个2个来,前面包车型大巴归来了,下1个再去,前边的没回去,前面包车型大巴就原地待命。

   
能够用上面包车型大巴代码来使用MyThread类。

  那里只是把宗旨的概念及原理做了叁个简练的阐释,不至于看前面包车型大巴次第时糊里凌乱的。具体哪些编写代码,上边的段落将做详细介绍。

class NewThread : MyThread
{
      override public void run()
      {
          Console.WriteLine(“使用MyThread建立并运转线程”);
      }
  }

 

  static void Main(string[] args)
  {

 

      NewThread nt = new NewThread();
      nt.start();
  }

  ③.创办四线程应用程序

     大家还足以应用MyThread来为线程传递任意复杂的参数。详细内容见下节。

  那里做叁个粗略的认证:上面首要透过介绍通过System.Threading命名空间的类、委托和BackgroundWorker组件二种差别的手段营造102线程应用程序,具体会从线程异步和线程同步四个方面来阐释。

3、    
为线程传递参数

  叁.一因而System.Threading命名空间的类构建

Thread类有3个带参数的信托项指标重载格局。这一个委托的概念如下:

  在.NET平台下,System.Threading命名空间提供了过三种类来营造二10三十二线程应用程序,能够说是专为四线程服务的。由于本文仅是想起到3个“进行试探”的作用,所以对于这一块不会追究过多、过深,首要利用System.Threading.Thread类。

[ComVisibleAttribute(false)]

  先从System.Threading.Thread类自身有关的三个小例子说到,代码如下,解释见注释:

public delegate void ParameterizedThreadStart(Object obj)

  using System;

本条Thread类的构造方法的概念如下:

  using System.Threading; //引进System.Threading命名空间

 

  namespace MultiThread

public Thread(ParameterizedThreadStart start);

  {

上边包车型地铁代码应用了那一个带参数的委托向线程传递三个字符串参数:

  class Class

public static void myStaticParamThreadMethod(Object obj)
{
    Console.WriteLine(obj);
}

  {

static void Main(string[] args)
{
      Thread thread = new Thread(myStaticParamThreadMethod);
      thread.Start(“通过信托的参数字传送值”);
}

  static void Main(string[] args)

要注意的是,假如运用的是不带参数的委托,无法动用带参数的Start方法运维线程,不然系统会抛出特别。但选用带参数的信托,可以采纳thread.Start()来运行线程,那时所传递的参数值为null。

  {

    也足以定义1个类来传递参数值,如下边包车型客车代码如下:

  Console.WriteLine(“**************
展现当前线程的相干音信 *************”);

class MyData
{
    private String d1;
    private int d2;
    public MyData(String d1, int d2)
    {
          this.d1 = d1;
          this.d2 = d2;
    }
    public void threadMethod()
    {
          Console.WriteLine(d1);
          Console.WriteLine(d2);
    }
}

  //注解线程变量并赋值为最近线程

MyData myData = new MyData(“abcd”,1234);
Thread thread = new Thread(myData.threadMethod);
thread.Start();

  Thread primaryThread = Thread.CurrentThread;

   
假使应用在其次节定义的MyThread类,传递参数会突显更简短,代码如下:

  //赋值线程的称呼

class NewThread : MyThread
{
    private String p1;
    private int p2;
    public NewThread(String p1, int p2)
    {
        this.p1 = p1;
        this.p2 = p2;
    }

  primaryThread.Name = “主线程”;

    override public void run()
    {
        Console.WriteLine(p1);
        Console.WriteLine(p2);
    }
}

  //显示线程的相干音讯

NewThread newThread = new NewThread(“hello world”, 4321);
newThread.start();

  Console.WriteLine(“线程的名字:{0}”, primaryThread.Name);

4、    
前台和后台线程

  Console.WriteLine(“线程是不是运行? {0}”, primaryThread.Is阿里ve);

    使用Thread建立的线程暗许情况下是前台线程,在经过中,只要有三个前台线程未脱离,进度就不会停下。主线程就是2个前台线程。而后台线程不管线程是不是终止,只要具有的前台线程都退出(包罗健康退出和越发退出)后,进度就会活动停止。一般后台线程用于拍卖时间较短的任务,如在3个Web服务器中得以运用后台线程来拍卖客户端发过来的请求新闻。而前台线程1般用来拍卖要求长日子等待的职责,如在Web服务器中的监听客户端请求的顺序,或是按期对少数系统财富举办围观的先后。上边包车型大巴代码演示了前台和后台线程的不同。

  Console.WriteLine(“线程的预先级: {0}”, primaryThread.Priority);

public static void myStaticThreadMethod()
{
    Thread.Sleep(3000);
}

  Console.WriteLine(“线程的意况: {0}”, primaryThread.ThreadState);

Thread thread = new Thread(myStaticThreadMethod);
// thread.IsBackground = true;
thread.Start();

  Console.ReadLine();

    借使运维方面包车型大巴代码,程序会等待3秒后退出,假设将注释去掉,将thread设成后台线程,则程序会应声退出。

  }

    要小心的是,必须在调用Start方法以前安装线程的项目,不然1但线程运维,将不能改动其体系。

  }

    通过BeginXXX方法运维的线程皆今后台线程

  }

5、  
判断四个线程是不是都截止的三种艺术

  输出结果如下:

规定全体线程是还是不是都成功了办事的方法有成都百货上千,如能够利用类似于对象计数器的法子,所谓目的计数器,正是三个目的被引述三次,那几个计数器就加一,销毁引用就减一,假使引用数为0,则垃圾搜聚器就会对那一个引用数为0的对象举行回收。

  ************** 突显当前线程的相关音讯
*************

情势1:线程计数器

  线程的名字:主线程

线程也能够行使计数器的不二等秘书技,即为全部需求监视的线程设2个线程计数器,每初叶3个线程,在线程的实践情势中为这一个计数器加一,若是有个别线程结束(在线程实践办法的末梢为那么些计数器减一),为那么些计数器减1。然后再初阶3个线程,按着一定的光阴间隔来监视这几个计数器,如是棕个计数器为0,表达具有的线程都得了了。当然,也足以不用那几个监视界程,而在每2个做事线程的终极(在为计数器减一的代码的背后)来监视这几个计数器,也正是说,每2个办事线程在剥离此前,还要承受检验这几个计数器。使用这种格局毫无忘了同步那个计数器变量啊,不然会发生意想不到的结局。

  线程是不是运行? True

方法二:使用Thread.join方法

  线程的事先级: 诺玛l

join方法唯有在线程截至时才继续试行下边包车型大巴话语。能够对每八个线程调用它的join方法,但要注意,那么些调用要在另贰个线程里,而不要在主线程,不然程序会被打断的。

  线程的场合: Running

    个人认为那种格局比较好。

  对于地方的代码不想做过多解释,只说一下Thread.CurrentThread获得的是实行当前代码的线程。

   
**线程计数器方法言传身教:

  3.一.1异步调用线程

**

  那里先说一下前台线程与后台线程。前台线程能挡住应用程序的截止,既直到全部前台线程终止后才会彻底关闭应用程序。而对后台线程来说,当有着前台线程终止时,后台线程会被活动结束,不论后台线程是或不是正在进行职务。默许景况下通过Thread.Start()方法创建的线程都自动为前台线程,把线程的性质IsBackground设为true时就将线程转为后台线程。

    class ThreadCounter : MyThread
    {
        private static int count = 0;
        private int ms;
        private static void increment()
        {
            lock (typeof(ThreadCounter))  // 必须共同计数器
            {
                count++;
            }
        }
        private static void decrease()
        {
            lock (typeof(ThreadCounter))
            {
                count–;
            }
        }
        private static int getCount()
        {
            lock (typeof(ThreadCounter))
            {
                return count;
            }
        }
        public ThreadCounter(int ms)
        {
            this.ms = ms;
        }
        override public void run()
        {
            increment();
            Thread.Sleep(ms);
            Console.WriteLine(ms.ToString()+”皮秒职责完结”);
            decrease();
            if (getCount() == 0)
                Console.WriteLine(“全体任务完结”);
        }
    }

  上面先看二个例证,该例子成立3个次线程试行打字与印刷数字的职分,而主线程则干任何的事,两者同时举办,互不干扰。

ThreadCounter counter1 = new ThreadCounter(3000);
ThreadCounter counter2 = new ThreadCounter(5000);
ThreadCounter counter3 = new ThreadCounter(7000);

  using System;

counter1.start();
counter2.start();
counter3.start();

  using System.Threading;

   
上面的代码固然在大多数的时候能够平常办事,但却存在一个隐患,就是只要有些线程,倘使是counter1,在运作后,由于某个原因,其余的线程并未有运营,在这种意况下,在counter壹运维完后,如故能够显示出“全体职务完成”的提醒新闻,不过counter二和counter三还尚未运转。为了消除那几个隐患,能够将increment方法从run中移除,将其内置ThreadCounter的构造方法中,在那时候,increment方法中的lock也可以去掉了。代码如:
        public ThreadCounter(int ms)
        {
            this.ms = ms;
            increment();
        }

  using System.Windows.Forms;

    运转方面包车型大巴次第后,将体现如图二的结果。

  namespace MultiThread

威尼斯人线上娱乐 2

  {

                                                                 图2

  class Class

动用Thread.join方法言传身教

  {

private static void threadMethod(Object obj)
{
    Thread.Sleep(Int32.Parse(obj.ToString()));
    Console.WriteLine(obj + “飞秒职责达成”);
}
private static void joinAllThread(object obj)
{
    Thread[] threads = obj as Thread[];
    foreach (Thread t in threads)
        t.Join();
    Console.WriteLine(“全体的线程停止”);
}

  static void Main(string[] args)

static void Main(string[] args)
{
    Thread thread1 = new Thread(threadMethod);
    Thread thread2 = new Thread(threadMethod);
    Thread thread3 = new Thread(threadMethod);

  {

     thread1.Start(3000);
     thread2.Start(5000);
     thread3.Start(7000);

  Console.WriteLine(“************* 八个线程同时事业
*****************”);

     Thread joinThread = new Thread(joinAllThread);
     joinThread.Start(new Thread[] { thread1, thread2, thread3 });

  //主线程,因为获得的是眼下在实行Main()的线程

}

  Thread primaryThread = Thread.CurrentThread;

    在运作方面包车型客车代码后,将会赢得和图二同样的运维结果。上述两种办法都并未有线程数的限制,当然,还是会蒙受操作系统和硬件财富的限量。**

  primaryThread.Name = “主线程”;

下一篇:**C#线程类别讲座(三):线程池和文件下载服务器

  Console.WriteLine(“-> {0} 在试行主函数 Main()。”,
Thread.CurrentThread.Name);

  //次线程,该线程指向PrintNumbers()方法

  Thread SecondThread = new Thread(new ThreadStart(PrintNumbers));

  SecondThread.Name = “次线程”;

  //次线程起先实行针对的办法

  SecondThread.Start();

  //同时主线程在实行主函数中的别的义务

  MessageBox.Show(“正在推行主函数中的职分。。。。”,
“主线程在职业…”);

  Console.ReadLine();

  }

  //打字与印刷数字的方式

  static void PrintNumbers()

  {

  Console.WriteLine(“-> {0} 在实践打字与印刷数字函数 PrintNumber()”,
Thread.CurrentThread.Name);

  Console.WriteLine(“打字与印刷数字: “);

  for (int i = 0; i < 10; i++)

  {

  Console.Write(“{0}, “, i);

  //Sleep()方法使当前线程挂等待钦命的时间长度在施行,那里重借使模仿打字与印刷职分

  Thread.Sleep(2000);

  }

  Console.WriteLine();

  }

  }

  }

  程序运营后会看到多个窗口弹出,如图所示,同时决定台窗口也在不停的显得数字。

    威尼斯人线上娱乐 3

  输出结果为:

  ************* 七个线程同时职业
*****************

  -> 主线程 在实行主函数 Main()。

  -> 次线程 在推行打字与印刷数字函数 PrintNumber()

  打字与印刷数字:

  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

 

上一页  [1] [2] [3] [4] [5] [6] 下一页

迎接进入.NET社区论坛,与200万手艺人员互动交流>>进入

 

  那里稍微对 Thread SecondThread = new Thread(new
ThreadStart(PrintNumbers)); 这一句做个表明。其实 ThreadStart 是
System.Threading 命名空间下的多少个信托,其宣称是 public delegate void
ThreadStart(),指向不带参数、重回值为空的章程。所以当使用 ThreadStart
时,对应的线程就只能调用不带参数、重返值为空的艺术。那非要指向含参数的不二等秘书籍吧?在System.Threading命名空间下还有七个ParameterizedThreadStart 委托,其声称是
public delegate void ParameterizedThreadStart(object obj),能够本着含
object 类型参数的方法,那里并非忘了 object
但是全数品类的父类哦,有了它就足以经过创设各样自定义类型,如结构、类等传递繁多参数了,那里就不再举例表达了。

  三.一.2并发难点

  那里再经过贰个例子让我们具体体会一下前方说起的面世难题,然后再介绍线程同步。

  using System;

  using System.Threading;

  namespace MultiThread1

  {

  class Class

  {

  static void Main(string[] args)

  {

  Console.WriteLine(“********* 并发难题演示
***************”);

  //创立三个打字与印刷对象实例

  Printer printer = new Printer();

  //声美素佳儿含几个线程对象的数组

  Thread[] threads = new Thread[10];

  for (int i = 0; i < 10; i++)

  {

  //将每三个线程都针对printer的PrintNumbers()方法

  threads[i] = new Thread(new ThreadStart(printer.PrintNumbers));

  //给每一个线程编号

  threads[i].Name = i.ToString() +”号线程”;

  }

  //开始试行全部线程

  foreach (Thread t in threads)

  t.Start();

  Console.ReadLine();

  }

  }

  //打印类

  public class Printer

  {

  //打字与印刷数字的艺术

  public void PrintNumbers()

  {

  Console.WriteLine(“-> {0} 正在执行打字与印刷职务,初步打字与印刷数字:”,
Thread.CurrentThread.Name);

  for (int i = 0; i < 10; i++)

  {

  Random r = new Random();

  //为了增加争辨的可能率及,使各线程各自等待随机的时间长度

  Thread.Sleep(2000 * r.Next(5));

  //打字与印刷数字

  Console.Write(“{0} “, i);

  }

  Console.WriteLine();

  }

  }

  }

  上面包车型地铁例子中,主线程产生的13个线程同时做客同一个指标实例printer的办法PrintNumbers(),由于未有锁定共享能源(注意,那里是指调控台),所以在PrintNumbers()输出到调整台在此之前,调用PrintNumbers()的线程很只怕被挂起,但不知晓如哪一天候(或是还是不是有)挂起,导致获得不可预测的结果。如下是五个例外的结果(当然,读者的运行结果可能会是别的景况)。

    威尼斯人线上娱乐 4

  情形一

    威尼斯人线上娱乐 5

  情形二

 

 

 

  叁.壹.三线程同步

  线程同步的走访格局也称之为阻塞调用,即未有实行完职责不回来,线程被挂起。能够运用C#中的lock关键字,在此关键字范围类的代码都将是线程安全的。lock关键字需定义二个标志,线程进入锁定范围是必须获得这几个符号。当锁定的是三个实例级对象的个体方法时选择办法自身所在对象的引用就能够了,将地点例子中的打字与印刷类Printer稍做退换,增加lock关键字,代码如下:

  //打印类

  public class Printer

  {

  public void PrintNumbers()

  {

  //使用lock关键字,锁定d的代码是线程安全的

  lock (this)

  {

  Console.WriteLine(“-> {0} 正在实践打字与印刷职分,开首打印数字:”,
Thread.CurrentThread.Name);

  for (int i = 0; i < 10; i++)

  {

  Random r = new Random();

  //为了增添争辨的概率及,使各线程各自等待随机的时间长度

  Thread.Sleep(2000 * r.Next(5));

  //打字与印刷数字

  Console.Write(“{0} “, i);

  }

  Console.WriteLine();

  }

  }

  }

  }

  同步后举行理并了结果如下:

    威尼斯人线上娱乐 6

  也得以运用System.Threading命名空间下的Monitor类举办协同,两者内涵是1致的,但Monitor类更加灵活,这里就不在做过多的钻探,代码如下:

  //打印类

  public class Printer

  {

  public void PrintNumbers()

  {

  Monitor.Enter(this);

  try

  {

  Console.WriteLine(“-> {0} 正在实行打字与印刷职分,先导打字与印刷数字:”,
Thread.CurrentThread.Name);

  for (int i = 0; i < 10; i++)

  {

  Random r = new Random();

  //为了增添抵触的可能率及,使各线程各自等待随机的时间长度

  Thread.Sleep(2000 * r.Next(5));

  //打字与印刷数字

  Console.Write(“{0} “, i);

  }

  Console.WriteLine();

  }

  finally

  {

  Monitor.Exit(this);

  }

  }

  }

  输出结果与地点的等同。

  三.贰通过委托创设十二线程应用程序

  在看上面包车型地铁内容时供给对信托有早晚的问询,假若不领会的话推荐参考一下和讯张子阳的《C# 中的委托和事件》,里面对信托与事件开始展览由浅入深的较系统的教授: http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html。

  那里先举二个有关信托的总结例子,具体解释见注释:

  using System;

  namespace MultiThread

  {

  //定义一个针对包括三个int型参数、重临值为int型的函数的信托

  public delegate int AddOp(int x, int y);

  class Program

  {

  static void Main(string[] args)

  {

  //创设一个指向Add()方法的AddOp对象p

  AddOp pAddOp = new AddOp(Add);

  //使用委托直接调用方法Add()

  Console.WriteLine(“10 + 25 = {0}”, pAddOp(10, 5));

  Console.ReadLine();

  }

  //求和的函数

  static int Add(int x, int y)

  {

  int sum = x + y;

  return sum;

  }

  }

  }

  运营结果为:

  10 + 25 = 15

 

 

 

  叁.二.壹线程异步

  先说惠氏(WYETH)下,这里不打算讲明委托线程异步或联合签名的参数字传送递、获取再次回到值等,只是做个常见的启幕而已,假使前面有时间了再别的写壹篇有关四线程中参数字传送递、获取重回值的篇章。

  注意观看地点的例证会意识,间接选拔委托实例 pAddOp(10, 五)
就调用了求和措施
Add()。很强烈,这一个方法是由主线程推行的。可是,委托项目中还有其它多少个点子——BeginInvoke()和EndInvoke(),上边通过切实的例子来阐明,将地方的例证做适度退换,如下:

  using System;

  using System.Threading;

  using System.Runtime.Remoting.Messaging;

  namespace MultiThread

  {

  //注解指向含七个int型参数、重返值为int型的函数的嘱托

  public delegate int AddOp(int x, int y);

  class Program

  {

  static void Main(string[] args)

  {

  Console.WriteLine(“******* 委托异步线程 五个线程“同时”工作
*********威尼斯人线上娱乐 ,”);

  //显示主线程的唯壹标示

  Console.WriteLine(“调用Main()的主线程的线程ID是:{0}.”,
Thread.CurrentThread.ManagedThreadId);

  //将委托实例指向Add()方法

  AddOp pAddOp = new AddOp(Add);

  //初阶委托次线程调用。委托BeginInvoke()方法重回的品种是IAsyncResult,

  //包蕴这委托指向方法甘休再次来到的值,同时也是EndInvoke()方法参数

  IAsyncResult iftAR = pAddOp.BeginInvoke(10, 10, null, null);

  Console.WriteLine(“”nMain()方法中实践其余职责……..”n”);

  int sum = pAddOp.EndInvoke(iftAR);

  Console.WriteLine(“10 + 10 = {0}.”, sum);

  Console.ReadLine();

  }

  //求和办法

  static int Add(int x, int y)

  {

  //提示调用该形式的线程ID,ManagedThreadId是线程的唯1标示

  Console.WriteLine(“调用求和办法 Add()的线程ID是: {0}.”,
Thread.CurrentThread.ManagedThreadId);

  //模拟二个经过,停留5秒

  Thread.Sleep(5000);

  int sum = x + y;

  return sum;

  }

  }

  }

  运行结果如下:

  ******* 委托异步线程 三个线程“同时”工作 *********

  调用Main()的主线程的线程ID是:拾.

  Main()方法中实行此外职责……..

  调用求和艺术 Add()的线程ID是: 7.

  10 + 10 = 20.

  叁.二.二线程同步

  委托中的线程同步重要涉嫌到地点运用的pAddOp.BeginInvoke(10, 10, null,
null)方法中前边三个为null的参数,具体的可以参照相关材质。这里代码如下,解释见代码注释:

  using System;

  using System.Threading;

  using System.Runtime.Remoting.Messaging;

  namespace MultiThread

  {

  //评释指向含四个int型参数、重临值为int型的函数的委托

  public delegate int AddOp(int x, int y);

  class Program

  {

  static void Main(string[] args)

  {

  Console.WriteLine(“******* 线程同步,“阻塞”调用,五个线程工作
*********”);

  Console.WriteLine(“Main() invokee on thread {0}.”,
Thread.CurrentThread.ManagedThreadId);

  //将委托实例指向Add()方法

  AddOp pAddOp = new AddOp(Add);

  IAsyncResult iftAR = pAddOp.BeginInvoke(10, 10, null, null);

  //剖断委托线程是不是施行完职务,

  //未遂的话,主线程就做别的的事

  while (!iftAR.IsCompleted)

  {

  Console.WriteLine(“Main()方法工作中…….”);

  Thread.Sleep(1000);

  }

  //得到重回值

  int answer = pAddOp.EndInvoke(iftAR);

  Console.WriteLine(“10 + 10 = {0}.”, answer);

  Console.ReadLine();

  }

  //求和艺术

  static int Add(int x, int y)

  {

  //提示调用该措施的线程ID,ManagedThreadId是线程的绝无仅有标示

  Console.WriteLine(“调用求和措施 Add()的线程ID是: {0}.”,
Thread.CurrentThread.ManagedThreadId);

  //模拟贰个进度,停留伍秒

  Thread.Sleep(5000);

  int sum = x + y;

  return sum;

  }

  }

  }

 

 

  运行结果如下:

  ******* 线程同步,“阻塞”调用,多少个线程工作 *********

  Main() invokee on thread 10.

  Main()方法工作中…….

  调用求和艺术 Add()的线程ID是: 七.

  Main()方法职业中…….

  Main()方法职业中…….

  Main()方法工作中…….

  Main()方法职业中…….

  10 + 10 = 20.

  3.3BackgroundWorker组件

  BackgroundWorker组件位于工具箱中,用于方便的创立线程异步的顺序。新建三个WindowsForms应用程序,分界面如下:

    威尼斯人线上娱乐 7

  代码如下,解释参见注释:

  private void button1_Click(object sender, EventArgs e)

  {

  try

  {

  //获得输入的数字

  int numOne = int.Parse(this.textBox1.Text);

  int numTwo = int.Parse(this.textBox2.Text);

  //实例化参数类

  AddParams args = new AddParams(numOne, numTwo);

  //调用RunWorkerAsync()生成后台线程,同时传入参数

  this.backgroundWorker1.RunWorkerAsync(args);

  }

  catch (Exception ex)

  {

  MessageBox.Show(ex.Message);

  }

  }

  //backgroundWorker新生成的线程开头职业

  private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)

  {

  //获取传入的AddParams对象

  AddParams args = (AddParams)e.Argument;

  //停留5秒,模拟耗费时间任务

  Thread.Sleep(5000);

  //返回值

  e.Result = args.a + args.b;

  }

  //当backgroundWorker一的DoWork中的代码执行完后会触发该事件

  //同时,其进行的结果会含有在RunWorkerCompleted伊夫ntArgs参数中

  private void backgroundWorker1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)

  {

  //展现运算结果

  MessageBox.Show(“运营结果为:” + e.Result.ToString(), “结果”);

  }

  }

  //参数类,那个类仅仅起到一个记录并传递参数的功效

  class AddParams

  {

  public int a, b;

  public AddParams(int numb1, int numb2)

  {

  a = numb1;

  b = numb2;

  }

  }

  注意,在盘算结果的还要,窗体能够轻巧活动,也足以再一次在文本框中输入消息,那就印证主线程与backgroundWorker组件生成的线程是异步的。

  4.总结

  本文从线程、进度、应用程序的涉嫌初叶,介绍了一部分有关十二线程的基本概念,同时阐述了线程异步、线程同步及出现难题等。最终从利用角度出发,介绍了什么样通过System.Threading命名空间的类、委托和BackgroundWorker组件等三种花招营造二十四线程应用程序。


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图