2016-08-15 3 views
-1

Я использую concurrentqueue, поэтому несколько пользователей могут записать свою информацию. На заднем плане я использую таймер, чтобы сэкономить все, что находится в очереди, в базу данных по времени. Мой код, как удар:Interlock compareexchange для коллекции

public void WriteInformation(sting msg) 
{ 
    ConcurrentQueue<MessageQueueItem> oldQueue; 
     do 
     { 
      oldQueue = messageQueue; 
      messageQueue.Enqueue(msg); 
     } 
     while (Interlocked.CompareExchange(ref oldQueue, null, messageQueue) != null); 
} 

В методе истечь мой таймер, я воссоздавая параллельную очередь и обработать старую очередь, как показано ниже:

var oldQueue = Volatile.Read(ref messageQueue); 
Volatile.Write(ref messageQueue, new ConcurrentQueue<string>()); 

// process the old queue; 
string item; 
if (oldQueue.TryDequeue(out item)) 
{ 
    // compact item and save to DB. 
} 

Является ли эта модель правильно? Также не думаю, что

var oldQueue = Volatile.Read(ref messageQueue); 
Volatile.Write(ref messageQueue, new ConcurrentQueue<string>()); 

необходим. Я могу использовать код ниже, как в моем методе WriteInformation, я уже проверяю, является ли messageQueue актуальной копией. Правильно ли это? WriteInformation и messageQueue являются статическими. Благодарю.

var oldQueue = messageQueue; 
messageQueue = new ConcurrentQueue<string>(); 

ответ

0

Вы не должны беспокоиться о неустойчивости одноточечной ссылки. Просто войдите в него через статическое поле или через инъекцию зависимостей после правильной инициализации. Какие другие потоки изменяются, это данные в очереди, а не ссылки на очередь. Ссылка не должна быть изменена после инициализации.

+0

действие DB довольно медленно, поэтому я хочу создать новую очередь для людей, чтобы вводить данные, а поток таймера может обрабатывать старую очередь в фоновом режиме. – Helic

+0

@Helic какая конкретная проблема решает вторая очередь? Почему вы не можете потреблять из той очереди, которая находится в очереди? – zerkms

+0

@zerkms, я думаю, что слишком частые вызовы метода WriteInformation будут блокировать сбор слишком много раз и задерживать действие БД, и наоборот – Helic