C#中有哪些线程通信的办法

发布时间 2023-05-09 10:17:07作者: yhm138
这里着重介绍如何在线程间通信,传递复杂的对象或者嵌套字典

问题

C#中有哪些线程通信的办法?
这里通信的内容可能很复杂,比如是一个对象,或者是一个嵌套字典。

给出具体的例子,需要你给出完整的C#文件。
比如说线程1需要随机生成一个Person对象,Person对象包括:年龄,性别,名称,一个大小为3的宠物数组pets。
每个宠物对象包括昵称,年龄。
线程2需要等待线程1生成完成后,才获取这个Person对象,打印这个Person对象的全部信息。

你可以使用线程安全的Collection类(如ConcurrentDictionary,ConcurrentQueue,ConcurrentBag,BlockingCollection,ConcurrentStack)或者共享内存进行通信。

常见的线程安全的Collection类

下面是一些常见的线程安全的Collection类及其特点:

ConcurrentDictionary:线程安全的键值对集合,可以在多个线程中同时进行添加、移除和访问操作。
ConcurrentStack:线程安全的后进先出(LIFO)堆栈,可以在多个线程中同时进行添加、移除和访问操作。
ConcurrentQueue:线程安全的先进先出(FIFO)队列,可以在多个线程中同时进行添加、移除和访问操作。

   
ConcurrentBag:线程安全的无序集合,可以在多个线程中同时进行添加、移除和访问操作。有TryAdd、TryTake、TryPeek等方法。
BlockingCollection:线程安全的集合,可以在多个线程中添加和移除元素,并支持阻塞式的读写操作。有Add、Take等方法。
它们的主要区别在于BlockingCollection支持阻塞式的读写操作,而ConcurrentBag不支持。

ConcurrentQueue代码

using System;
using System.Collections.Concurrent;
using System.Threading;

class Program
{
    static ConcurrentQueue<Person> queue = new ConcurrentQueue<Person>();

    static void Main(string[] args)
    {
        Thread t1 = new Thread(new ThreadStart(Producer));
        Thread t2 = new Thread(new ThreadStart(Consumer));

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }

    static void Producer()
    {
        Random random = new Random();
        Person person = new Person();
        person.Age = random.Next(20, 40);
        person.Name = "John Doe";
        person.Gender = "Male";
        person.Pets = new Pet[3];
        for (int i = 0; i < 3; i++)
        {
            Pet pet = new Pet();
            pet.Name = $"Pet {i + 1}";
            pet.Age = random.Next(1, 10);
            person.Pets[i] = pet;
        }

        queue.Enqueue(person);
    }

    static void Consumer()
    {
        Person person;
        while (!queue.TryDequeue(out person))
        {
            Thread.Sleep(100);
        }

        Console.WriteLine($"Name: {person.Name}");
        Console.WriteLine($"Age: {person.Age}");
        Console.WriteLine($"Gender: {person.Gender}");
        Console.WriteLine("Pets:");
        foreach (var pet in person.Pets)
        {
            Console.WriteLine($"Name: {pet.Name}, Age: {pet.Age}");
        }
    }
}

class Person
{
    public int Age { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public Pet[] Pets { get; set; }
}

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}