Что такое быстрый и эффективный способ передачи данных между потоками в C #? - PullRequest
6 голосов
/ 10 января 2012

У меня однопроцессное, двухпотоковое приложение.Поток 1 будет прослушивать поток рыночных данных и обновлять самые последние котировки по тысячам акций.Поток 2 запустит таймер с частотой выборки и сделает снимок самых последних цитат для обработки.По сути, мне нужно уменьшить скорость чрезвычайно быстрой подачи рыночных данных.

Мое первое предположение о решении - использовать BlockingQueue.Для этого мне нужно переместить функцию таймера в поток 1, что я могу сделать, проверяя часы каждый раз, когда приходит обновление цитаты, и отправляя снимок цитат в очередь с частотой выборки.Меня беспокоит то, что очередь будет занимать много памяти, а сборка мусора замедлит работу.

Мое второе предположение - заставить поток 1 скопировать данные в заблокированный элемент с частотой выборки, который поток 2может получить доступ.Мое беспокойство здесь заключается в том, что блокировки будут медленными.

Думаю, это сделает примитивы цитат нестабильными.Поскольку один поток только пишет, а один поток только читает, может быть, это уместно?

Существует ли лучший способ обмена данными между потоками для этого приложения, чувствительного к задержке?Это не сверхвысокочастотное приложение.Я могу терпеть задержки порядка десятков мс.

Ответы [ 2 ]

7 голосов
/ 10 января 2012

Если у вас есть только 2 потока, обращающихся к этому ресурсу (то есть одновременное чтение не требуется), то самым простым (и одним из самых быстрых) будет просто использовать ключевое слово lock:

public class QuoteStore
{
    private readonly List<Quote> _quotes = new List<Quote>();
    private readonly object _mutex = new object();

    public ReadOnlyCollection<Quote> GetQuotes()
    {
      lock (_mutex)
      {
        return _quotes.ToReadOnly();
      }
    }

    public void AddQuote()
    {
      lock (_mutex)
      {
        _quotes.Add(quote);
      }
    }
}

Если, однако, требуется одновременное чтение, это было бы хорошо для класса ReaderWriterLockSlim . Вы можете получить блокировку чтения при копировании данных и блокировку записи при записи данных, например:

public class QuoteStore : IDisposable
{
    private readonly ReaderWriterLockSlim _mutex = new ReaderWriterLockSlim();
    private readonly List<Quote> _quotes = new List<Quote>();

    public ReadOnlyCollection<Quote> GetQuotes()
    {
      _mutex.EnterReadLock();
      try
      {
        return _quotes.ToReadOnly();
      }
      finally
      {
        _mutex.ExitReadLock();
      }
    }

    public void AddQuote()
    {
      _mutex.EnterWriteLock();
      try
      {
        _quotes.Add(quote);
      }
      finally
      {
        _mutex.ExitWriteLock();
      }
    }

    public void Dispose() 
    {
        _mutex.Dispose();
    }
}

Или, если вы используете .Net 4 или выше, в пространстве имен System.Collections.Concurrent есть много замечательных одновременно изменяемых коллекций, которые вы, вероятно, можете использовать без каких-либо проблем (они являются объектами без блокировки и как правило, очень быстро - и некоторые улучшения производительности также появятся в .Net 4.5 !).

0 голосов
/ 21 апреля 2012

Разве это не случай Продюсер-Потребительская Очередь? Потребитель будет ждать (Monitor.Wait), когда источник будет пульсировать при поступлении нового канала. Как только поступят новые / обновленные каналы, источник заполнит очередь и сработает Monitor.Pulse.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...