2014-10-16 6 views
1

Мне нужно избавиться от блокировок в моем приложении C#, используя класс Interlocked. У меня есть такой код:Программирование без блокировок с использованием блокированного класса

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]++; 
     } 
     } 
    } 
} 

И когда я хочу, чтобы заменить замок в ThreadProc на Interlocked класса, например:

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)

Как это исправить?

+1

Добавить «реф» на место вызова. (Что, кстати сказать, не означает, что остальная часть вашего подхода гарантирована последующим ... незакрепленным кодом часто бывает очень сложно, даже экспертами). –

+0

@PeterDuniho, это не помогает – pragmus

+1

А ... Я вижу. Вы используете «ulong». Вы можете использовать только подписанные ints с Interlocked.Increment, а не без знака. –

ответ

2

При вызове функции блокировки необходимо использовать ref.Increment.

Interlocked.Increment(ref myLong); 

или в случае

Interlocked.Increment(ref m_logStruct.errorCodes[fullErrCode]); 

Важно понимать, что Interlocked.Increment(ref long) является ...

truly atomic only on systems where a System.IntPtr is 64 bits long. On other systems, these methods are atomic with respect to each other, but not with respect to other means of accessing the data. Thus, to be thread safe on 32-bit systems, any access to a 64-bit value must be made through the members of the Interlocked class.

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]++; 
} 

будет тривиальными и неважными для большинства применений.

UPDATE

Похоже, ваш тип данных без знака. Посмотрите на решении Джона Скита для использования Interlocked.Increment с беззнаковыми типами:

https://stackoverflow.com/a/934677/141172