刚才想了半天文章应该起什么名字,最后决定起名为《线程安全使用》,线程安全这个词很难理解,感觉就像托管这词一样,但是托管翻译成英文是managed,我通常把他翻译成被管理,这样就好理解多了,线程安全也是一样,可以理解为可以被多个线程同时使用的集合,而且同时使用的时候是该集合的值是准确的。

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

下面举一个使用线程安全集合的例子,使用的是BlockingCollection,个人觉得这个集合是够用了,其他集合和这个集合基本上大同小异,没什么大区别。但是根据官方解释ConcurrentBag是适用于快速删除和添加,具体为什么他适用,而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<int> blocking = new BlockingCollection<int>(); static void Main(string[] args)
{ blocking = new BlockingCollection<int>();
Console.WriteLine("当前blocking为:" + blocking.IsCompleted + "设置了集合大小count一样是0,blocking.Count:" + blocking.Count());
//当前线程标识
Console.WriteLine(Thread.CurrentThread.GetHashCode()); for (int i = ; i < ; i++)
{
////如果添加到第3个,就设置添加完成,这时在添加就会抛异常
//if (i == 3)
//{
// blocking.CompleteAdding();
//} Action<object> action = new Action<object>(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.Invoke(),并发调用ACtion,可以传多个action,也可以传一个action数据组。

Task(action<t>,object),这是Task的构造方法,接受action,注意object是action的参数,但是解释中并没有说的很明白。(翻译坑,你懂的),根据MSDN提供的构造方法,并没有接受action<t,t>,action<t,t,t>这样的,也就是说,定义函数时,要传递一个实体,而不要传递多个参数,否则任务调用不了。

task.RunSynchronously(),根据MSDN解释,他是同步运行任务计划用的,同时他和task.Start()一样,也可以启动线程。

BlockingCollection集合

属性一:IsCompleted,他是表示集合是否有数据,只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false。

PS:这个解释如果你要看MSDN一辈子都想不明白,msdn的中文翻译真心坑。

属性一:BlockingCollection.IsAddingCompleted,表示是否添加完成。针对blocking.CompleteAdding()的使用,当调用了该方法IsAddingCompleted就为true。

方法一:BlockingCollection.blocking.CompleteAdding(),设置IsAddingCompleted用的。

方法二:BlockingCollection.Add,添加一个实体

方法三:BlockingCollection.TryAdd,添加一个实体,我这里用的是这个方法,区别是,如果添加重复项,他会引发InvalidOperationException这个异常。

方法四:BlockingCollection.Take,从集合中取一个值,注意,是真的取出来,取出来后,BlockingCollection.cout会减一。

运行结果如下:

今天先写到这,写文字还真是累,明明没写几个字。。。

----------------------------------------------------------------------------------------------------

注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!

C#线程安全使用(二)的更多相关文章

  1. Android线程管理(二)——ActivityThread

    线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...

  2. juc线程池原理(二):ThreadPoolExecutor的成员变量介绍

    概要 线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析ThreadPoolExecutor类,来了解线程池的原理. ThreadPoolExecutor数据结构 Thread ...

  3. HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

    HDFS源码分析数据块复制监控线程ReplicationMonitor(二)

  4. 线程池系列二:ThreadPoolExecutor讲解

    一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...

  5. Java 线程池(二)

    简介 在上篇 Java 线程池(一) 我们介绍了线程池中一些的重要参数和具体含义,这篇我们看一看在 Java 中是如何去实现线程池的,要想用好线程池,只知其然是远远不够的,我们需要深入实现源码去了解线 ...

  6. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  7. Java之线程处理之二

    No.1编写一个打印机类 写两个方法 public class Printer { public void print1() { System.out.print("微"); Sy ...

  8. Java 7 Concurrency Cookbook 翻译 第一章 线程管理之二

    三.中断一个线程 一个拥有多个线程的Java程序要结束,需要满足两个条件之一:一是所有的非后台线程都执行结束了:二是某个线程执行了 System.exit() 方法.当你想要终结一个运行中的Java程 ...

  9. android 进程/线程管理(二)----关于线程的迷思

    一:进程和线程的由来 进程是计算机科技发展的过程的产物. 最早计算机发明出来,是为了解决数学计算而发明的.每解决一个问题,就要打纸带,也就是打点. 后来人们发现可以批量的设置命令,由计算机读取这些命令 ...

  10. Linux线程学习(二)

    线程基础 进程 系统中程序执行和资源分配的基本单位 每个进程有自己的数据段.代码段和堆栈段 在进行切换时需要有比较复杂的上下文切换   线程 减少处理机的空转时间,支持多处理器以及减少上下文切换开销, ...

随机推荐

  1. Dockerfile中COPY命令的简单性

    dockerfile中的COPY命令是不会拷贝目录结构的,它只会单纯把包含的所有文件拷贝到另一个目录中去. 相关链接:https://www.cnblogs.com/sparkdev/p/957324 ...

  2. centos7 安装python3.7.11 笔记

    安装python依赖包yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-deve ...

  3. GitLab在centos7上安装和使用

    git的优点 git是分布式的,svn不是 git分布式本地就可以用,可以随便保存各种历史痕迹,不用担心污染服务器,连不上服务器也能提交代码.查看log. GIT分支和SVN的分支不同 分支在SVN中 ...

  4. idhttp提交post带参数并带上cookie

    有这么一个提交连接 http://www.XXXXXX.com/test.php?p1=411328&p2=1&d1=HeroSkinList 一共有三个参数[p1]  [p2]  [ ...

  5. 华为ssh远程登录,配置

  6. 让数字变化炫酷起来,数字滚动Text组件[Unity]

    让数字滚动起来 上周我的策划又提了样需求,当玩家评分发生变动时,屏幕出现人物评分浮层UI,播放评分数字滚动动画.这类数字滚动需求非常常见,我就按一般思路,将startvalue与endvalue每隔一 ...

  7. imagecreatefrombmp、imagebmp php处理bmp文件

    /*格式组成典型的BMP图像文件由四部分组成: 1:位图头文件数据结构,它包含BMP图像文件的类型.显示内容等信息: 2:位图信息数据结构,它包含有BMP图像的宽.高.压缩方法,以及定义颜色等信息: ...

  8. VS2017Release+x64失败,LNK1104,无法打开文件"msvcprt.lib"

    采用VS2017+Qt5.10联合开发环境建立开发,将Qt的库包含到VS中使用VS2017的Debug+x64模式调试程序,通过并出现对应的EXE应用程序! 但是转换到Release+x64模式出现问 ...

  9. swust oj 1051

    输出利用先序遍历创建的二叉树中的指定结点的孩子结点 1000(ms) 10000(kb) 2432 / 5430 利用先序递归遍历算法创建二叉树并输出该二叉树中指定结点的儿子结点.约定二叉树结点数据为 ...

  10. NeuChar 平台使用及开发教程 索引

    什么是 NeuChar? NeuChar 是由盛派(Senparc)团队发布的新一代跨平台服务系统,其中包含了开放的跨平台通讯标准及核心计算模块(Senparc.NeuChar.dll)以及配套的云管 ...