欢迎访问yhm138的博客园博客, 你可以通过 [RSS] 的方式持续关注博客更新

MyAvatar

yhm138

HelloWorld!

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

这里着重关注如何在线程间通信,传递对象

问题

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代码

TIO

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));

        //Thread.Start方法用于启动一个新线程并执行线程的入口点,该入口点是由ThreadStart委托或ParameterizedThreadStart委托指定的。一旦线程被启动,它将开始执行指定的方法,直到完成或被中止。
        t1.Start();
        t2.Start();

        t1.Join(); //Thread.Join方法用于阻塞当前线程。这里,直到目标线程执行完毕Main线程才继续执行
        t2.Join();//Thread.Join方法用于阻塞当前线程。这里,直到目标线程执行完毕Main线程才继续执行

        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; }
}
posted @ 2023-05-09 10:07  yhm138  阅读(271)  评论(0编辑  收藏  举报