[英]Using thread-safe ConcurrentDictionary collection
I've a such function which uses unthread-safe collection List, also to be thread-safe it uses lock-operator: 我有一个这样的函数,它使用非线程安全的集合列表,也为了线程安全,它使用了锁操作符:
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();
}
I want to convert it to do it lock-free. 我想将其转换为无锁。 To do it I've used in this function ConcurrentDictionary collection instead of List collection, so my function begin look so: 为此,我在此函数中使用ConcurrentDictionary集合而不是List集合,因此我的函数开始看起来像这样:
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!");
}
}
But in this function I begin get error(Index is out of range). 但是在此函数中,我开始出现错误(索引超出范围)。 How to use thread-safe collection(ConcurrentDictionary) correctly? 如何正确使用线程安全集合(ConcurrentDictionary)? How to fix my error? 如何解决我的错误?
It's not going to be concurrent if you're replacing the variable where you're storing the list. 如果要在存储列表的位置替换变量,则不会是并发的。 You need to use the concurrent methods that it provides. 您需要使用它提供的并发方法。 See the examples in the MSDN article . 请参阅MSDN文章中的示例。
Use TryAdd
, TryUpdate
, TryRemove
or AddOrUpdate
in order to add to the list or update the list so rather than: 使用TryAdd
, TryUpdate
, TryRemove
或AddOrUpdate
以添加到列表或更新列表,这样,而不是:
dmReqList = m_logStruct.domainName;
Do something like: 做类似的事情:
foreach (var item in m_logStruct.domainName)
{
dmReqList.TryAdd(item.Key, item.Value);
}
UPDATE: As pointed out by Alexei, you're defining the dmReqList locally. 更新:正如Alexei指出的那样,您正在本地定义dmReqList。 This means that you're getting no benefit from it being a ConcurrentDictionary because no other thread could access it anyway. 这意味着您不能从ConcurrentDictionary中受益,因为任何其他线程都无法访问它。 Also, you imply from your original example that m_logStruct is accessible via other threads because you applied the lock to it. 另外,您从原始示例中暗示m_logStruct可通过其他线程访问,因为您已对其施加了锁定。 If the implication is correct, then that is what needs to be a ConcurrentDictionary. 如果含义正确,那么这就是ConcurrentDictionary。 So, your code would need to look more like this: 因此,您的代码将需要看起来像这样:
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.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.