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