c# - 从列表中添加和删除时出现“索引超出范围”错误
问题描述
我想向列表中添加/删除,但出现“索引超出范围”异常。在我的代码中,我在一秒钟内添加数据 2 次,直到 10 次。我使用线程将它们删除。我也使用信号量进行阻塞。我想同时使用 3 个线程。
这是我的代码
class Program
{
private static Thread[] threads = new Thread[3];
private static Semaphore sem = new Semaphore(3, 3);
private static List<string> messagesList = new List<string>();
private static readonly object _kilit = new object();
static void Main(string[] args)
{
Thread addData = new Thread(AddData);
addData.Start();
for (int j = 0; j < 3; j++)
{
threads[j] = new Thread(AddComma);
threads[j].Name = "thread_" + j;
threads[j].Start();
}
}
public static void AddData()
{
for (int i = 0; i < 10; i++)
{
messagesList.Add("data");
messagesList.Add("data");
Thread.Sleep(1000);
}
}
public static void AddComma()
{
sem.WaitOne();
while (true) {
if (messagesList.Count > 0)
{
Console.WriteLine();
Console.WriteLine(Thread.CurrentThread.Name + "Entering to Critical section");
int averageIndex = messagesList[0].ToString().Length / 2; // Here is the error
string msg = messagesList[0].ToString().Substring(0, averageIndex) + "," + messagesList[0].ToString().Substring(averageIndex);
Console.WriteLine(msg);
messagesList.RemoveAt(0);
Console.WriteLine(Thread.CurrentThread.Name + "Exiting from Critical Section");
}
}
sem.Release();
}
}
解决方案
您允许三个线程同时运行:
new Semaphore(3, 3);
所以你Semaphore
并没有真正帮助你,因为你并没有真正阻止。因此,您仍然会遇到问题,例如,您可能会在列表中留下一条消息,但 3 个线程都评估messagesList.Count > 0
为true
. 其中一个线程将首先从列表中删除该项目,这将导致其他两个抛出异常。
有更好的方法来做到这一点。对于列表,我喜欢使用ReaderWriterLockSlim
具有读锁和写锁的 。它允许所有线程读取,但一旦您获得写入锁,就会阻止所有人。文档中有一个如何使用它的示例。
推荐阅读
- python - 如何删除标签 Python
- javascript - 我能否澄清一下全局范围、全局对象、全局对象和全局变量的术语?
- flutter - 接收方:空 E/颤振(4835):尝试调用:[](“数据”)
- java - 在 weblogic 12C 本地服务器上部署的 Eclipse 和 Java 配置不起作用
- python - 从 VBA 运行 Python 脚本,不工作
- php - 基于游戏时间的排行榜排名 MySQL PHP
- python - 尝试在 pandas 数据框中使用 explode 导致数据没有变化
- amazon-web-services - 如何在 Dynamodb 解析器请求映射中使用查询参数形成密钥?
- java - 为什么我不能使用子类中的受保护方法?
- scalardb - 如何在 ScalarDB 上实现应用程序级分页