Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.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# 使用线程安全的ConcurrentDictionary集合_C#_Multithreading_Thread Safety_Concurrentdictionary - Fatal编程技术网

C# 使用线程安全的ConcurrentDictionary集合

C# 使用线程安全的ConcurrentDictionary集合,c#,multithreading,thread-safety,concurrentdictionary,C#,Multithreading,Thread Safety,Concurrentdictionary,我有一个这样的函数,它使用非线程安全的集合列表,为了线程安全,它使用锁操作符: public void ShowData(ref DataGridView dmRequests, ref DataGridView URL, ref DataGridView dmData, ref DataGridView errorCodes) { List<KeyValuePair<string, ulong>> dmReqList = new List<KeyValue

我有一个这样的函数,它使用非线程安全的集合列表,为了线程安全,它使用锁操作符:

public void ShowData(ref DataGridView dmRequests, ref DataGridView URL, ref DataGridView dmData, ref DataGridView errorCodes)
{
    List<KeyValuePair<string, ulong>> dmReqList = new List<KeyValuePair<string, ulong>>();
    List<KeyValuePair<string, ulong>> urlReqList = new List<KeyValuePair<string, ulong>>(); 
    List<KeyValuePair<string, ulong>> dmDataList = new List<KeyValuePair<string, ulong>>();
    List<KeyValuePair<string, ulong>> errCodesList = new List<KeyValuePair<string, ulong>>();

    lock (m_logStruct.domainName)
    {
        dmReqList = m_logStruct.domainName.ToList();
    }
    lock(m_logStruct.URL)
    {
        urlReqList = m_logStruct.URL.ToList();
    }
    lock(m_logStruct.domainData)
    {
        dmDataList = m_logStruct.domainData.ToList();
    }
    lock(m_logStruct.errorCodes)
    {
        errCodesList = m_logStruct.errorCodes.ToList();
    }

    dmRequests.DataSource = dmReqList.OrderBy(x => x.Key).ToList();
    URL.DataSource = urlReqList.OrderBy(x => x.Key).ToList();
    dmData.DataSource = dmDataList.OrderBy(x => x.Key).ToList();
    errorCodes.DataSource = errCodesList.OrderBy(x => x.Key).ToList();
}
public void ShowData(ref-DataGridView-dmRequests、ref-DataGridView-URL、ref-DataGridView-dmData、ref-DataGridView-errorcode)
{
List dmReqList=新列表();
List urlReqList=新列表();
List dmDataList=新列表();
List errCodesList=新列表();
锁(m_logStruct.domainName)
{
dmReqList=m_logStruct.domainName.ToList();
}
锁(m_logStruct.URL)
{
urlReqList=m_logStruct.URL.ToList();
}
锁(m_logStruct.domainData)
{
dmDataList=m_logStruct.domainData.ToList();
}
锁(m_logStruct.errorCodes)
{
errCodesList=m_logStruct.errorCodes.ToList();
}
dmRequests.DataSource=dmReqList.OrderBy(x=>x.Key).ToList();
URL.DataSource=urlReqList.OrderBy(x=>x.Key).ToList();
dmData.DataSource=dmDataList.OrderBy(x=>x.Key).ToList();
errorCodes.DataSource=errCodesList.OrderBy(x=>x.Key).ToList();
}
我想把它转换成无锁的。为此,我在函数ConcurrentDictionary集合中使用了ConcurrentDictionary集合,而不是List集合,因此我的函数begin看起来是这样的:

public void ShowData(ref DataGridView dmRequests, ref DataGridView URL, ref DataGridView dmData, ref DataGridView errorCodes)
{
    try
    {
        ConcurrentDictionary<string, ulong> dmReqList = new ConcurrentDictionary<string, ulong>();
        ConcurrentDictionary<string, ulong> urlReqList = new ConcurrentDictionary<string, ulong>();
        ConcurrentDictionary<string, ulong> dmDataList = new ConcurrentDictionary<string, ulong>();
        ConcurrentDictionary<string, ulong> errCodesList = new ConcurrentDictionary<string, ulong>();

        dmReqList = m_logStruct.domainName;
        urlReqList = m_logStruct.URL;
        dmDataList = m_logStruct.domainData;
        errCodesList = m_logStruct.errorCodes;

        dmRequests.DataSource = dmReqList.OrderBy(x => x.Key);
        URL.DataSource = urlReqList.OrderBy(x => x.Key).ToList();//I get error here: Index is out of range                
        dmData.DataSource = dmDataList.OrderBy(x => x.Key).ToList();              
        errorCodes.DataSource = errCodesList.OrderBy(x => x.Key).ToList();
    }
    catch(IOException e)
    {
        MessageBox.Show(e + " Something bad has been occurred here!");
    }

}
public void ShowData(ref-DataGridView-dmRequests、ref-DataGridView-URL、ref-DataGridView-dmData、ref-DataGridView-errorcode)
{
尝试
{
ConcurrentDictionary dmReqList=新建ConcurrentDictionary();
ConcurrentDictionary urlReqList=新建ConcurrentDictionary();
ConcurrentDictionary dmDataList=新建ConcurrentDictionary();
ConcurrentDictionary errCodesList=新建ConcurrentDictionary();
dmReqList=m_logStruct.domainName;
urlReqList=m_logStruct.URL;
dmDataList=m_logStruct.domainData;
errCodesList=m_logStruct.errorCodes;
dmRequests.DataSource=dmReqList.OrderBy(x=>x.Key);
URL.DataSource=urlReqList.OrderBy(x=>x.Key).ToList();//我在这里得到错误:索引超出范围
dmData.DataSource=dmDataList.OrderBy(x=>x.Key).ToList();
errorCodes.DataSource=errCodesList.OrderBy(x=>x.Key).ToList();
}
捕获(IOE异常)
{
Show(e+“这里发生了不好的事情!”);
}
}

但在这个函数中,我开始得到错误(索引超出范围)。如何正确使用线程安全集合(ConcurrentDictionary)?如何修复我的错误?

如果在存储列表的地方替换变量,则不会并发。您需要使用它提供的并发方法。请参见中的示例

使用
TryAdd
TryUpdate
TryRemove
AddOrUpdate
添加到列表或更新列表,而不是:

dmReqList = m_logStruct.domainName;
做一些类似于:

foreach (var item in m_logStruct.domainName)
{
    dmReqList.TryAdd(item.Key, item.Value);
}
更新:正如Alexei所指出的,您正在本地定义dmReqList。这意味着,作为ConcurrentDictionary,您不会从中受益,因为其他线程无论如何都无法访问它。另外,从最初的示例中可以看出,m_logStruct可以通过其他线程访问,因为您对其应用了锁。如果含义是正确的,那么这就是ConcurrentDictionary所需要的。因此,您的代码需要看起来更像这样:

private ConcurrentDictionary<string, ulong> _domainNames = new ConcurrentDictionary<string, ulong>();

public void ShowData(ref DataGridView dmRequests)
{
    dmRequests.DataSource = _domainNames.OrderBy(x => x.Key);  //Set the current values of the dictionary to the grid.
}

public void MultiThreadedMethod()
{
    _domainNames.TryAdd(someKey, someValue);  //Access the dictionary from multiple threads.
}
私有ConcurrentDictionary _domainNames=新ConcurrentDictionary();
public void ShowData(ref DataGridView dmRequests)
{
dmRequests.DataSource=_domainNames.OrderBy(x=>x.Key);//将字典的当前值设置为网格。
}
public void多线程方法()
{
_domainNames.TryAdd(someKey,someValue);//从多个线程访问字典。
}

您声明了新词典,但随后立即覆盖它们。您可以删除所有的
新ConcurrentDictionary()
在函数中,它们不为您做任何事情。您的示例显示的代码不能向多个线程公开变量(所有局部变量)考虑更新您的代码,以显示多个线程如何访问<代码> ErrCODESList之类的东西。侧注释:请考虑将样本裁减到仅仅一组集合。在每个函数中有4个几乎相同的部分不提供任何附加信息。关于如何使用
ConcurrentDictionary
的问题此建议允许从多个线程访问
m_logStruct
,因此完全不支持线程安全。与常规列表/字典相比,对任何其他线程都不可见的局部变量使用
ConcurrentDictionary
不会使代码更“线程安全”。OP没有提供m_logStruct的定义,但根据约定,我们可以假设这是一个私有全局变量。的确,如果多个线程可以访问m_logStruct并对其进行更改,那么“可能”并不完全是线程安全的,但我们必须假设OP已经知道这一点,因为他并不担心访问m_logStruct,而是担心dmReqList。此外,dmReqList不是局部变量。如果你看OP的方法定义,他是通过引用将其传递到方法中的。“dmReqList不是一个局部变量”-它比什么?请注意,原始代码锁定在
lock(m_logStruct.domainName)
上,因此看起来像
m_logStruct
,其字段需要保护。。。(注意,提供的示例有些随机代码,即通过引用传递所有参数或锁定字段而不是单独的对象,因此这可能意味着OP不太关心特定的代码,只对使用
ConcurrentDictionary
)哦,关于dmReqList,您是对的。我看错了。我将更新我的答案,这也将涉及你的其他声明。