这篇文章主要讲解了“C#线程完成数实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#线程完成数实例分析”吧!

解决一个问题

假如,程序需要向一个 Web 发送 5 次请求,受网路波动影响,有一定几率请求失败。如果失败了,就需要重试。

示例代码如下:

classProgram{privatestaticintcount=0;staticvoidMain(string[]args){for(inti=0;i<5;i++)newThread(HttpRequest).Start();//创建线程//用于不断向另一个线程发送信号while(count<5){Thread.Sleep(100);}Console.WriteLine("任务执行完毕");}//模拟网络请求publicstaticvoidHttpRequest(){Console.WriteLine("开始一个任务");//随机生成一个数,如果为偶数,则模拟请求失败boolisSuccess=(newRandom().Next(0,10))%2==0;//......模拟请求HTTPThread.Sleep(TimeSpan.FromSeconds(2));//请求失败则重试if(!isSuccess){Console.WriteLine($"请求失败,count={count}");newThread(()=>{HttpRequest();}).Start();return;}//完成一次任务,+1Interlocked.Add(refcount,1);Console.WriteLine($"完成任务,count={count}");}}

代码太糟糕了,但我们可以使用 CountdownEvent 类来改造它。

CountdownEvent 类

表示在计数变为零时处于有信号状态的同步基元。

也就是说,设定一个计数器,每个线程完成后,就会减去 1 ,当计数器为 0 时,代表所有线程都已经完成了任务。

构造函数和方法

CountdownEvent 类的构造函数如下:

构造函数说明CountdownEvent(Int32)使用指定计数初始化 CountdownEvent 类的新实例。

CountdownEvent 类的常用方法如下:

方法说明AddCount()将 CountdownEvent 的当前计数加 1。AddCount(Int32)将 CountdownEvent 的当前计数增加指定值。Reset()将 CurrentCount 重置为 InitialCount 的值。Reset(Int32)将 InitialCount 属性重新设置为指定值。Signal()向 CountdownEvent 注册信号,同时减小 CurrentCount 的值。Signal(Int32)向 CountdownEvent 注册多个信号,同时将 CurrentCount 的值减少指定数量。TryAddCount()增加一个 CurrentCount 的尝试。TryAddCount(Int32)增加指定值的 CurrentCount 的尝试。Wait()阻止当前线程,直到设置了 CountdownEvent 为止。Wait(CancellationToken)阻止当前线程,直到设置了 CountdownEvent 为止,同时观察 CancellationToken。Wait(Int32)阻止当前线程,直到设置了 CountdownEvent 为止,同时使用 32 位带符号整数测量超时。Wait(Int32, CancellationToken)阻止当前线程,直到设置了 CountdownEvent 为止,并使用 32 位带符号整数测量超时,同时观察 CancellationToken。Wait(TimeSpan)阻止当前线程,直到设置了 CountdownEvent 为止,同时使用 TimeSpan 测量超时。Wait(TimeSpan, CancellationToken)阻止当前线程,直到设置了 CountdownEvent 为止,并使用 TimeSpan 测量超时,同时观察 CancellationToken。

API 比较多,没事,我们来慢慢了解它。

示例

我们来编写一个场景代码,一个有五件事,需要完成,分别派出 5 个人去实现。

.Wait();用在一个线程中,这个线程将等待其它完成都完成任务后,才能继续往下执行。

Signal();用于工作线程中,向 CountdownEvent 对象发送信号,告知线程已经完成任务,然后CountdownEvent.CurrentCount将减去 1。

当计数器为 0 时,阻塞的线程将恢复执行。

代码示例如下:

classProgram{//手头上有5件事privatestaticCountdownEventcountd=newCountdownEvent(5);staticvoidMain(string[]args){Console.WriteLine("开始交待任务");//同时叫5个人,去做5件事for(inti=0;i<5;i++){Threadthread=newThread(DoOne);thread.Name=$"{i}";thread.Start();}//等他们都完成事情countd.Wait();Console.WriteLine("任务完成,线程退出");Console.ReadKey();}publicstaticvoidDoOne(){intn=newRandom().Next(0,10);//模拟要n秒才能完成Thread.Sleep(TimeSpan.FromSeconds(n));//完成了,减去一件事countd.Signal();Console.WriteLine($"{Thread.CurrentThread.Name}完成一件事了");}}

示例很简单,每个线程在完成自己的任务时,需要调用Signal()方法,使得计数器减去1。

.Wait();可以等待所有的任务完成。

需要注意的是,如果不调用Signal()或者计数器一直不为0,那么Wait()将无限等待。

当然,Wait()可以设置等待时间,

另外我们也看到了常用方法中有AddCount()Reset()等。

这个类的等待控制方式比较宽松,Wait()后,到底什么时候才能执行,全凭其它线程自觉。

如果发现线程执行任务失败,我们可以不调用Signal()或者 使用AddCount()来增加次数,进行重试

感谢各位的阅读,以上就是“C#线程完成数实例分析”的内容了,经过本文的学习后,相信大家对C#线程完成数实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!