C#线程安全使用(二)

C#线程安全使用(二),第1张

概述刚才想了半天文章应该起什么名字,最后决定起名为《线程安全使用》,线程安全这个词很难理解,感觉就像托管这词一样,但是托管翻译成英文是managed,我通常把他翻译成被管理,这样就好理解多了,线程安全也是

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

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

下面举一个使用线程安全集合的例子,使用的是BlockingCollection,个人觉得这个集合是够用了,其他集合和这个集合基本上大同小异,没什么大区别。但是根据官方解释ConcurrentBag是适用于快速删除和添加,具体为什么他适用,而BlockingCollection不适用,我也没找到原因。

<span >namespace<span > ParallelConsole
{
<span >class
<span > Program
{

    </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;定义集合大小为51个,也可以不定义大小</span>    <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;static</span> BlockingC<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>lection<<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;int</span>> blocking = <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;new</span> BlockingC<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>lection<<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;int</span>>(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800080;"&gt;51</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt;);    </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;static</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;vo<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a></span> Main(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;string</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt;[] args)    {        blocking </span>= <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;new</span> BlockingC<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>lection<<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;int</span>><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt;();        Cons<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>e.Write<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>ne(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;当前blocking为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span> + blocking.IsCompleted + <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;<a href="https://m.jb51.cc/tag/shezhi/" target="_blank" >设置</a>了集合大小count一样是0,blocking.Count:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span> +<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt; blocking.Count());        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;当前线程标识</span>

<span > Console.Writeline(Thread.CurrentThread.GetHashCode());

        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;for</span> (<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;int</span> i = <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800080;"&gt;0</span>; i < <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800080;"&gt;3</span>; i++<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt;)        {            </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #808080;"&gt;///</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;/如果<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>到第3个,就<a href="https://m.jb51.cc/tag/shezhi/" target="_blank" >设置</a><a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>完成,这时在<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>就会抛异常</span>            <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;if (i == 3)            </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;{            </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;    blocking.CompleteAdding();            </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;}</span>

<span >
Action<<span >object> action = <span >new Action<<span >object><span >(run);
Task task = <span >new<span > Task(action,i);
task.RunSynchronously();
}
Console.Writeline(<span >"<span >设置添加完成前:<span >" +<span > blocking.IsAddingCompleted);
<span >//<span >设置添加完成后
<span > blocking.CompleteAdding();
Console.Writeline(<span >"<span >设置添加完成后:<span >" +<span > blocking.IsAddingCompleted);
<span >#region 同步取 取3个
<span >//<span >for (int i = 0; i < 3; i++)
<span >//<span >{
<span >//<span > Action actionTake = new Action(take);
<span >//<span > actionTake();
<span >//<span >}
<span >#endregion
<span >//<span >并发读取

        <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;#region</span> 并发步取 取3个        <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;blocking.IsCompleted 只有当集合被<a href="https://www.jb51.cc/tag/tianjia/" target="_blank" >添加</a>进<a href="https://www.jb51.cc/tag/neirong/" target="_blank" >内容</a>,<a href="https://m.jb51.cc/tag/ranhou/" target="_blank" >然后</a>又都被取光了以后,他才会等于ture,否则都是false        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;当IsCompleted为ture时,就不能再取了否则会抛异常        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;同时取,结果是         </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;blocking:0        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;blocking:2        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;blocking:1</span>        <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;if</span> (!blocking.IsCompleted)<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;如果集合没取光</span>

<span > {
Action actionTake2 = <span >new<span > Action(take);
Parallel.Invoke(actionTake2,actionTake2,actionTake2);
}
<span >#endregion<span >

        Cons<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>e.Write<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>ne(</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;当前blocking为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span> + blocking.IsCompleted +  <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;,blocking<a href="https://www.jb51.cc/tag/shuliang/" target="_blank" >数量</a>为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span> +<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt; blocking.Count());        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;数据被取光了以后, blocking.Count()为0</span>

<span > Console.Read();
}

    </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;static</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;vo<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a></span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt; take()    {        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;//</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #008000;"&gt;<a href="https://m.jb51.cc/tag/tongbu/" target="_blank" >同步</a>取,blocking.Count()会真实的表现,而异步取,Count是不准确的,因为我取count的时候,可能集合已经又被取出数据了,测试10次肯定会出现不真实的情况</span>        Cons<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>e.Write<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>ne(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;blocking:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span> + blocking.Take() + <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;,blocking<a href="https://www.jb51.cc/tag/shuliang/" target="_blank" >数量</a>为:</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #800000;"&gt;"</span> +<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt; blocking.Count());    }    </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;static</span> <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;vo<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a></span> run(<span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;object</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt; i)    {        </span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;int</span> currentI = <span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #0000ff;"&gt;int</span><span https://m.jb51.cc/tag/color/" target="_blank" >color</a>: #000000;"&gt;.Parse(i.ToString());        blocking.TryAdd(currentI);     }}

}

解释几个方法:

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

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

 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#线程安全使用(二)全部内容,希望文章能够帮你解决C#线程安全使用(二)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1264260.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存