C#线程安全使用(二)

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

刚才想了半天文章应该起什么名字,最后决定起名为《线程安全使用》,线程安全这个词很难理解,感觉就像托管这词一样,但是托管翻译成英文是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>(51);
      
        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 = 0; i < 3; 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); 
        }
    }
}
View Code

解释几个方法:

 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会减一。

运行结果如下:

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

目录
相关文章
|
5月前
|
安全 数据库连接 API
C#一分钟浅谈:多线程编程入门
在现代软件开发中,多线程编程对于提升程序响应性和执行效率至关重要。本文从基础概念入手,详细探讨了C#中的多线程技术,包括线程创建、管理及常见问题的解决策略,如线程安全、死锁和资源泄露等,并通过具体示例帮助读者理解和应用这些技巧,适合初学者快速掌握C#多线程编程。
103 0
|
6月前
|
数据采集 XML JavaScript
C# 中 ScrapySharp 的多线程下载策略
C# 中 ScrapySharp 的多线程下载策略
|
6月前
|
安全 C# 开发者
【C# 多线程编程陷阱揭秘】:小心!那些让你的程序瞬间崩溃的多线程数据同步异常问题,看完这篇你就能轻松应对!
【8月更文挑战第18天】多线程编程对现代软件开发至关重要,特别是在追求高性能和响应性方面。然而,它也带来了数据同步异常等挑战。本文通过一个简单的计数器示例展示了当多个线程无序地访问共享资源时可能出现的问题,并介绍了如何使用 `lock` 语句来确保线程安全。此外,还提到了其他同步工具如 `Monitor` 和 `Semaphore`,帮助开发者实现更高效的数据同步策略,以达到既保证数据一致性又维持良好性能的目标。
81 0
|
8月前
|
并行计算 算法 C#
C# Mandelbrot和Julia分形图像生成程序更新到2010-9-14版 支持多线程计算 多核处理器
此文档是一个关于分形图像生成器的介绍,作者分享了个人开发的M-J算法集成及色彩创新,包括源代码和历史版本。作者欢迎有兴趣的读者留言交流,并提供了邮箱(delacroix_xu@sina.com)以分享资源。文中还展示了程序的发展历程,如增加了真彩色效果、圈选放大、历史记录等功能,并分享了几幅精美的分形图像。此外,还提到了程序的新特性,如导入ini文件批量输出图像和更新一批图片的功能。文档末尾附有多张程序生成的高分辨率分形图像示例。
|
8月前
|
大数据 C#
C#实现多线程的几种方式
C#实现多线程的几种方式
|
9月前
|
安全 Java C#
C#多线程详解
C#多线程详解
90 0
|
9月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
238 3
|
9月前
|
C#
C#学习系列相关之多线程(二)----Thread类介绍
C#学习系列相关之多线程(二)----Thread类介绍
|
9月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结