Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多线程增加int_C#_Multithreading_Int - Fatal编程技术网

C# 多线程增加int

C# 多线程增加int,c#,multithreading,int,C#,Multithreading,Int,当多个线程试图增加int时,我遇到了一个问题。下面是我的代码: private int _StoreIndex; private readonly List<Store> _Stores = new List<Store>(); public void TestThreads() { _StoreIndex = 0; for (int i = 0; i < 20; i++) { Thread thread = new Th

当多个线程试图增加int时,我遇到了一个问题。下面是我的代码:

private int _StoreIndex;
private readonly List<Store> _Stores = new List<Store>();

public void TestThreads()
{
    _StoreIndex = 0;

    for (int i = 0; i < 20; i++)
    {
        Thread thread = new Thread(() =>
            {
                while (_StoreIndex < _Stores.Count - 1)
                {
                    _Stores[Interlocked.Increment(ref _StoreIndex)].CollectData();
                }
            });
        thread.Start();
    }
}
private int\u StoreIndex;
私有只读列表_Stores=new List();
公共void TestThreads()
{
_StoreIndex=0;
对于(int i=0;i<20;i++)
{
线程线程=新线程(()=>
{
而(\u StoreIndex<\u Stores.Count-1)
{
_存储[Interlocated.Increment(参考_StoreIndex)].CollectData();
}
});
thread.Start();
}
}
我希望每次线程执行此代码时,int都会增加1。然而,事实并非如此。我也尝试过使用lock(newobject()),但效果不太好。问题是并非所有存储都收集数据,因为(在调试时),\u StoreIndex的值类似于0、1、1、3、4、5。列表中的第二个对象显然被跳过


我做错了什么?提前感谢。

在您的情况下,我将首先使用TPL来避免手动创建线程和索引时出现的所有这些问题:

Parallel.ForEach(_Stores, (store) => store.CollectData());

在您的情况下,我将首先使用TPL来避免手动创建线程和索引的所有这些问题:

Parallel.ForEach(_Stores, (store) => store.CollectData());

我认为应该更正为:

Thread thread = new Thread(() =>
{
    int index = 0;
    while ((index = Interlocked.Increment(ref _StoreIndex)) < _Stores.Count - 1)
    {
         _Stores[index].CollectData();
    }
});
Thread-Thread=新线程(()=>
{
int指数=0;
而((索引=联锁。增量(参考存储索引))<\u Stores.Count-1)
{
_存储[index].CollectData();
}
});

现在索引是本地的,所以没有干扰,而_StoreIndex只在单个位置原子地使用。

我认为应该将其更正为:

Thread thread = new Thread(() =>
{
    int index = 0;
    while ((index = Interlocked.Increment(ref _StoreIndex)) < _Stores.Count - 1)
    {
         _Stores[index].CollectData();
    }
});
Thread-Thread=新线程(()=>
{
int指数=0;
而((索引=联锁。增量(参考存储索引))<\u Stores.Count-1)
{
_存储[index].CollectData();
}
});

现在索引是本地的,因此没有干扰,而_StoreIndex只在单个位置原子地使用。

这不是原子操作:

_Stores[Interlocked.Increment(ref _StoreIndex)].CollectData();

增量是原子的,但此行包含的代码比简单的增量多。您可能需要先整理您的文件夹,然后使用线程安全的集合来保存您的商店,比如ConcurrentBag,或者考虑TPL库和类,如“代码>任务< /代码>和<代码>并行< /代码>来执行工作量。

< P>这不是一个原子操作:

_Stores[Interlocked.Increment(ref _StoreIndex)].CollectData();


增量是原子的,但此行包含的代码比简单的增量多。您可能需要先整理您的文件夹,然后使用线程安全集合来保存您的商店,比如ConcurrentBag,或者考虑TPL库和类,如“代码>任务< /代码>和<代码>并行< /代码>来执行工作负载。

您确实意识到<代码>(而“StureCuths:AsSturysCuffice 1”)将跳过最后一个存储区,你不觉得吗?更常见的情况是
while(\u StoreIndex<\u Stores.Count)
或不太常见的
while(\u StoreIndex
lock(new object())
永远不会锁定代码。您希望锁定单个对象的实例,而不是每次锁定一个新对象。请记住,有些线程可能会在while中检查条件,然后处理递增的值-您肯定需要用一个锁锁定这些线程中对_StoreIndex的所有访问。也许您希望使用
Parallel.ForEach()
?@phoog如果它是
而(\u StoreIndex<\u Stores.Count)
,那么在上一次迭代中
\u StoreIndex
将是
\u Stores.Count-1
。然后它将增加1,成为
\u Stores.Count
。引用
\u Stores[\u Stores.Count]
会引发异常。多线程访问
列表
这不是线程安全的。您确实意识到
while(\u StoreIndex<\u Stores.Count-1)
将跳过最后一个存储,不是吗?更常见的情况是
while(\u StoreIndex<\u Stores.Count)
或不太常见的
while(\u StoreIndex
锁定(新对象)())()
?@phoog如果它是
而(\u StoreIndex<\u Stores.Count)
,则在上一次迭代中
\u StoreIndex
将是
\u Stores.Count-1
。然后它将增加1,并成为
\u Stores.Count
。引用
\u Stores[\u Stores.Count]
将引发异常。多线程访问
列表
不是线程安全的在并行访问
\u存储
\u存储索引
时存在问题(竞争条件)。这个答案解决了什么问题?@L.B:这段代码试图通过将数组中每个单独元素的处理转换为一个单独的任务并将其提供给线程池来绕过在每个线程中增加索引。这是对原始问题的更干净的重写,并且是正确的。@BrokenGlass,是的,您是正确的。只需编辑您的a拒绝撤消downvote@BrokenGlass我不知道并行命名空间中的For和ForEach。感谢您的回答,尽管For更适合我的需要。在并行访问
\u Stores
\u StoresIndex
时存在问题(竞争条件)。这个答案解决了什么问题?@L.B:这段代码试图通过将数组中每个单独元素的处理转换为一个单独的任务并将其提供给线程池来绕过在每个线程中增加索引。这是对原始问题的更干净的重写,并且是正确的。@BrokenGlass,是的,您是正确的。只需编辑您的a拒绝撤消downvote@BrokenGlass我不知道并行名称空间中的For和ForEach。感谢您的回答,尽管For更适合我的需要。这样我就不需要线程,我可以轻松地从mai运行此代码