【问题标题】:Two threads trying to access same List :" System.ArgumentOutOfRangeException"两个线程试图访问同一个列表:“System.ArgumentOutOfRangeException”
【发布时间】:2021-12-06 00:22:49
【问题描述】:

我是线程新手。我有一个列表和 2 个线程 T1 和 T2。

private readonly List<item> myCompletedItems;

我有一个设置集合的方法

public void ItemCreated(item theitem)
{
this.myCompletedItems.add(theitem);
}

我有另一种方法可以获取第一项的字段值:

public int GetStartItemId()
{          
  return this.myCompletedItems[0].id;                
}

线程 1 正在将项目添加到“myCompletedItems”。但即使在将项目添加到列表之前,线程 2 也会尝试访问列表并抛出“System.ArgumentOutOfRangeException:索引超出范围”。如何让线程 2 等到线程 1 将所有项目添加到列表中?

【问题讨论】:

  • 你把球扔给朋友,他们试图把球扔给另一个朋友。如果不同步会发生什么?有人把球打在脸上......这比那更糟糕,你已经硬连线了一个事实,即某人的手中总是有一个球。首先,您需要使用lock 来同步列表访问,其次,您需要(至少)检查是否确实存在数组元素0(也在锁中)
  • 可能想先阅读一些关于基本线程安全问题并处理此类问题 - hamidmosalla.com/2018/07/09/thread-safety ;在这种情况下,lock 就足够了,请参阅 docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
  • 您正在尝试实现名为producer/consumer problem 的东西。要做到这一点并不容易。我建议您对此进行一些修改。您可能会发现这很有用makolyte.com/…
  • 我可以在这里使用阻塞收集吗?
  • 当然可以,但是,您实际上想做什么,这将使某人更好地回答问题。也就是说,如果你解释你为什么需要这个,你要解决什么问题,可能会有很多合适的模式和解决方案

标签: c# multithreading thread-safety


【解决方案1】:

常规列表不是线程安全的,当尝试从多个线程同时使用它时,几乎任何事情都可能发生。

如何让线程 2 等到线程 1 将所有项目添加到列表中?

如果您想确保两个线程不会同时访问资源,请使用lock,或者使用manualResetEvent/autoResetEvent 来阻塞一个线程,直到另一个线程执行某些操作。

或者更实际地,使用concurrent collections

然而,多线程并不是一个胡乱尝试的好地方。这将很容易导致难以重现的错误。即使对于经验丰富的程序员来说,多线程也很困难,并且您应该对deadlocks and race conditions 等潜在危险有相当好的了解在尝试使用多线程之前。另请参阅 asynchronous programmingDataFlow,这些部分是为了避免线程之间手动同步的需要。

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多