C# task应用实例详解

2020-05-29 15:01:00王冬梅

ConCurrent的线程安全的

因为,MSDN将在System.Collections.Concurrent命名空间下的集合,都称为线程安全的集合。

线程安全可以理解为可以被多个线程同时使用的集合,而且同时使用的时候是该集合的值是准确的。

下面举一个使用线程安全集合的例子,使用的是BlockingCollection。

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

namespace ParallelConsole
{
 class Program
 {
 
 //定义集合大小为51个,也可以不定义大小
 static BlockingCollection blocking = new BlockingCollection(51);
 
 static void Main(string[] args)
 {
  

  blocking = new BlockingCollection();
  Console.WriteLine("当前blocking为:" + blocking.IsCompleted + "设置了集合大小count一样是0,blocking.Count:" + blocking.Count());
  //当前线程标识
  Console.WriteLine(Thread.CurrentThread.GetHashCode());

  for (int i = 0; i < 3; i++)
  {
  ////如果添加到第3个,就设置添加完成,这时在添加就会抛异常
  //if (i == 3)
  //{
  // blocking.CompleteAdding();
  //}
  
  Action action = new Action(run);
  Task task = new Task(action,i); 
  task.RunSynchronously(); 
  }
  Console.WriteLine("设置添加完成前:" + blocking.IsAddingCompleted);
  //设置添加完成后
  blocking.CompleteAdding();
  Console.WriteLine("设置添加完成后:" + blocking.IsAddingCompleted);
  #region 同步取 取3个
  //for (int i = 0; i < 3; i++)
  //{
  // Action actionTake = new Action(take);
  // actionTake();
  //}
  #endregion
  //并发读取
  
  #region 并发步取 取3个
  //blocking.IsCompleted 只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false
  //当IsCompleted为ture时,就不能再取了否则会抛异常
  
  //同时取,结果是 
  //blocking:0
  //blocking:2
  //blocking:1
  if (!blocking.IsCompleted)//如果集合没取光
  {
  Action actionTake2 = new Action(take);
  Parallel.Invoke(actionTake2, actionTake2, actionTake2);
  }
  #endregion

  Console.WriteLine("当前blocking为:" + blocking.IsCompleted + ",blocking数量为:" + blocking.Count());
  //数据被取光了以后, blocking.Count()为0
  Console.Read();
 }

 public static void take()
 {
  //同步取,blocking.Count()会真实的表现,而异步取,Count是不准确的,因为我取count的时候,可能集合已经又被取出数据了,测试10次肯定会出现不真实的情况
  Console.WriteLine("blocking:" + blocking.Take() + ",blocking数量为:" + blocking.Count());
 }
 public static void run(object i)
 {
  int currentI = int.Parse(i.ToString());
  blocking.TryAdd(currentI); 
 }
 }
}

Parallel

Parallel.Invoke(),并发调用Action,可以传多个Action,也可以传一个Action数据组。

Task

Task(Action,object),这是Task的构造方法,接收Action,object是Action的参数,。