我想在C#中模拟生产者Consumer。一个线程作为生成器,新的数组对象,并将该数组放入List.Another线程作为comsumer工作,当List中有元素时,它得到数组并做一些东西。代码在这里。为什么在这个过程中有" null" s。怎么解决? 调用list.add(tmp)时mybe引起的问题,在ushort [] tmp准备好之前添加了一个list.Count。任何人都可以解释这个过程的机制。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace listTest
{
class Program
{
static List<ushort[]> list = new List<ushort[]>();
static void func1()
{
while (true)
{
ushort[] tmp;
while (true)
{
tmp = new ushort[100];
if (tmp != null)
break;
}
list.Add(tmp);
Thread.Sleep(10);
}
}
static void func2()
{
while (true)
{
if (list.Count > 0)
{
ushort[] data = list.ElementAt(0);
if (data == null)
Console.Write("null\n");
else
{
for (int i = 0; i < data.Length; i++)
{
data[i] += 1;
}
}
Console.Write("ok ");
list.RemoveAt(0);
}
}
}
static void Main(string[] args)
{
Thread func1T = new Thread(func1);
Thread func2T = new Thread(func2);
func1T.Start();
func2T.Start();
}
}
}
答案 0 :(得分:1)
您有时会获得null的问题是使用Add和ElementAt操作对列表进行并发访问。因为在你的情况下,ElementAt不必枚举列表,它将在内部检查列表是否为空,如果不是,它将返回指定索引处的元素,如list[index]
。这非常轻量级,因此您的问题在于Add操作的来源。
Add操作首先在内部检查其当前容量是否足够大,以便可以添加新元素(它在内存中保留的位数多于它包含的元素数量+ 1)。如果可以添加它,只需通过语句_items[_size++] = item;
如果之前未分配足够大小,Add操作将创建一个新数组,其中包含所需的新大小。之后,之前太小的数组中的元素需要复制到新数组中。这通过Array.Copy
操作发生。之后,内部保持的元素数量增加,然后元素本身被添加。
正如你所看到的,幕后有很多事情要发生。我个人不知道问题究竟来自哪里。我最好的猜测是内部数组中的内存已经分配,但是在使用ElementAt操作访问它时未设置该值。
此类问题是您需要管理对共享资源(可跨线程共享的资源)的访问权限的原因。有几种技术可用于锁,监视器,信号量等......
您还可以将集合的类型更改为thread-safe collection,以处理同步问题。