问题
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; }
}