C#中的多线程小试牛刀中的多线程小试牛刀
前言前言
昨天在上班时浏览博问,发现了一个问题,虽然自己在 C# 多线程上没有怎么尝试过,看了几遍 CLR 中关于 线程的概念和讲解(后面三
章)。也想拿来实践实践。问题定义是这样的:
对于多线程不是很懂,面试的时候遇到一个多线程的题,不会做,分享出来,懂的大佬指点一下,谢谢
建一个winform窗体,在窗体中放上一个开始按钮,一个停止按钮,一个文本框,在窗体中声明一个List类型的属性,点击开始按
钮后开启10个线程,所有线程同时不间断的给List集合中添加1-10000之间的随机数,要求添加List集合中的数字不能重复,并且
实时在文本框中显示集合的长度,当集合List的长度等于1000时自动停止所有线程,如果中途点击停止按钮也停止所有线程,点
击开始又继续执行。
我其实没有完全实现了这位博问中提问的同学的需求,具体问题的来源可查看该地址 问题来源
开始尝试开始尝试
刚拿到这个需求的时候,映入我脑海里的是 Task, Threadpool,Concurrent,和 Lock 等概念,接下来就是组装和编码的过程了,首先理一
理头绪,
生成随机数
插入到 List 中,且不能重复
开启多个线程同时插入。
首先是生成 随机数,使用 System.Random 类来生成伪随机数(这个其实性能和效率贼低,后面再叙述)
private int GenerateInt32Num()
{
var num = random.Next(0, TOTAL_NUM);
return num;
}
然后是插入到 List<Int32> 中的代码,判断是否 已经达到了 我们需要的 List 长度,如果已满足,则退出程序。
private void AddToList(int num)
{
if (numList.Count == ENDNUM)
{
return;
}
numList.Add(num);
}
如果是个 单线程的,按照上面那样 while(true) 然后一直插入即可,可这个是个 多线程,那么需要如何处理呢?
我思考了一下,想到了之前在 CLR 中学到的 可以用 CancellationTokenSource 中的 Cancel 来通知 Task 来取消操作。所以现在的逻辑是,
用线程池来实现多线程。然后传入 CancellationTokenSource.Token 来取消任务。
最后用 Task.WhanAny() 来获取到第一个到达此 Task 的 ID。
首先是建立 Task[] 的数组
internal void DoTheCompeteSecond()
{
Task[] tasks = new Task[10];
for (int i = 0; i < 10; ++i)
{
int num = i;
tasks[i] = Task.Factory.StartNew(() => AddNumToList(num, cts), cts.Token);
}
Task.WaitAny(tasks);
}
然后 AddNumToList 方法是这样定义的,
private void AddNumToList(object state, CancellationTokenSource cts)
{-
Console.WriteLine("This is the {0} thread,Current ThreadId={1}",
state,
Thread.CurrentThread.ManagedThreadId);
while (!cts.Token.IsCancellationRequested)
{
if (GetTheListCount() == ENDNUM)