加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#线程安全使用(二)

发布时间:2020-12-15 04:46:14 所属栏目:百科 来源:网络整理
导读:刚才想了半天文章应该起什么名字,最后决定起名为《线程安全使用》,线程安全这个词很难理解,感觉就像托管这词一样,但是托管翻译成英文是managed,我通常把他翻译成被管理,这样就好理解多了,线程安全也是一样,可以理解为可以被多个线程同时使用的集合,

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

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

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

<span style="color: #0000ff;">namespace<span style="color: #000000;"> ParallelConsole
{
<span style="color: #0000ff;">class
<span style="color: #000000;"> Program
{

    </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;定义集合大小为51个,也可以不定义大小</span>
    <span style="color: #0000ff;"&gt;static</span> BlockingCollection<<span style="color: #0000ff;"&gt;int</span>> blocking = <span style="color: #0000ff;"&gt;new</span> BlockingCollection<<span style="color: #0000ff;"&gt;int</span>>(<span style="color: #800080;"&gt;51</span><span style="color: #000000;"&gt;);

    </span><span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span> Main(<span style="color: #0000ff;"&gt;string</span><span style="color: #000000;"&gt;[] args)
    {


        blocking </span>= <span style="color: #0000ff;"&gt;new</span> BlockingCollection<<span style="color: #0000ff;"&gt;int</span>><span style="color: #000000;"&gt;();
        Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;当前blocking为:</span><span style="color: #800000;"&gt;"</span> + blocking.IsCompleted + <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;设置了集合大小count一样是0,blocking.Count:</span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; blocking.Count());
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;当前线程标识</span>

<span style="color: #000000;"> Console.WriteLine(Thread.CurrentThread.GetHashCode());

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

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

        <span style="color: #0000ff;"&gt;#region</span> 并发步取 取3个
        <span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;blocking.IsCompleted 只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;当IsCompleted为ture时,就不能再取了否则会抛异常

        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;同时取,结果是 
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;blocking:0
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;blocking:2
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;blocking:1</span>
        <span style="color: #0000ff;"&gt;if</span> (!blocking.IsCompleted)<span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;如果集合没取光</span>

<span style="color: #000000;"> {
Action actionTake2 = <span style="color: #0000ff;">new<span style="color: #000000;"> Action(take);
Parallel.Invoke(actionTake2,actionTake2,actionTake2);
}
<span style="color: #0000ff;">#endregion<span style="color: #000000;">

        Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;当前blocking为:</span><span style="color: #800000;"&gt;"</span> + blocking.IsCompleted +  <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;,blocking数量为:</span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; blocking.Count());
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;数据被取光了以后, blocking.Count()为0</span>

<span style="color: #000000;"> Console.Read();
}

    </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; take()
    {
        </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;同步取,blocking.Count()会真实的表现,而异步取,Count是不准确的,因为我取count的时候,可能集合已经又被取出数据了,测试10次肯定会出现不真实的情况</span>
        Console.WriteLine(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;blocking:</span><span style="color: #800000;"&gt;"</span> + blocking.Take() + <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;,blocking数量为:</span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; blocking.Count());
    }
    </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;static</span> <span style="color: #0000ff;"&gt;void</span> run(<span style="color: #0000ff;"&gt;object</span><span style="color: #000000;"&gt; i)
    {
        </span><span style="color: #0000ff;"&gt;int</span> currentI = <span style="color: #0000ff;"&gt;int</span><span style="color: #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会减一。

运行结果如下:

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读