我需要使用Interlocked类处理C#应用程序中的锁。我有这样的代码:
class LogStruct
{
public Dictionary<string, ulong> domainName;
public Dictionary<string, ulong> URL;
public Dictionary<string, ulong> domainData;
public Dictionary<string, ulong> errorCodes;
public LogStruct()
{
domainName = new Dictionary<string, ulong> { };
URL = new Dictionary<string, ulong> { };
domainData = new Dictionary<string, ulong> { };
errorCodes = new Dictionary<string, ulong> { };
}
}
class CLogParser
{
string domainName = parameters[0];
string errorCode = matches[1].Value;
LogStruct m_logStruct;
...
public CLogParser()
{
m_logStruct = new LogStruct();
}
...
public void ThreadProc(object param)
{
if (m_logStruct.errorCodes.ContainsKey(fullErrCode))
{
lock (m_logStruct.errorCodes)
{
m_logStruct.errorCodes[fullErrCode]++;
}
}
}
}
当我想替换Interlocked类上ThreadProc中的锁时,例如:
public void ThreadProc(object param)
{
if (m_logStruct.errorCodes.ContainsKey(fullErrCode))
{
Interlocked.Increment(m_logStruct.errorCodes[fullErrCode]);
}
}
我得到这个错误:
Error CS1502: The best overloaded method match for
`System.Threading.Interlocked.Increment(ref int)'
has some invalid arguments (CS1502) (projectx)
以及此错误:错误CS1503:参数#1' cannot convert
ulong to ref int'(CS1503)(projectx)
如何修复?
调用Interlocked.Increment时需要使用ref
,例如
Interlocked.Increment(ref myLong);
或者在您的情况下是
Interlocked.Increment(ref m_logStruct.errorCodes[fullErrCode]);
重要的是要认识到Interlocked.Increment(ref long)
是…
只有在System.IntPtr为64位长的系统上才是真正的原子。在其他系统上,这些方法相对于彼此是原子的,但相对于访问数据的其他方式不是原子的。因此,为了在32位系统上实现线程安全,对64位值的任何访问都必须通过Interlocked类的成员进行。
http://msdn.microsoft.com/en-us/library/zs86dyzy(v=vs.110).aspx
附带说明一下,之间的实际性能差异
Interlocked.Increment(ref m_logStruct.errorCodes[fullErrCode]);
和
lock(myLock)
{
m_logStruct.errorCodes[fullErrCode]++;
}
对于大多数应用程序来说都是微不足道的。
更新
看起来你的数据类型是无符号的。看看Jon Skeet使用Interlocked.Increment的无符号类型的解决方案:
https://stackoverflow.com/a/934677/141172