Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a fast, memory efficient way to pass data between threads in C#?

Tags:

c#

concurrency

I have a one-process, two-thread application. Thread 1 will listen to a market data feed and update the most recent quote on thousands of stocks. Thread 2 will run a timer at a Sampling Frequency and take a snapshot of the most recent quotes for processing. Effectively, I need to down-sample an extremely fast market data feed.

My first guess at a solution is to use a BlockingQueue. To do this I need to move the timer functionality into Thread 1, which I can do by checking the clock every time a quote update comes in and send a snapshot of the quotes onto the queue at the Sampling Frequency. My concern here is that the queue will consume a lot of memory and garbage collection will slow things down.

My second guess is to have Thread 1 copy the data into a locked member at the Sampling Frequency, which Thread 2 can access. My concern here is that the locks will be slow.

My thirt guess it to make the quote primitives volatile. Since one thread only writes and one thread only reads, maybe this is appropriate?

Is there a best practice way to communicate the data between the threads for this latency sensitive application? This is not an ultra-high frequency application. I can tolerate latencies on the order of tens of ms.

like image 369
Rich C Avatar asked Jan 10 '12 14:01

Rich C


People also ask

How to transfer data between threads in C?

Threads are sharing the same memory space so you can use ordinary variable to share data between threads. You are also mentioning about thread waiting for some event, this is another story - synchronization. For this purpose you can use mutexses for example.

What is the most efficient way for 2 threads to share information?

If you want synchronous communication between a main thread and a processing thread, you can use a SynchronousQueue. The idea is that the main thread passes data to the processing thread by calling put() , and the processing thread calls take() .

How do I transfer data between two threads?

A synchronization point at which two threads can pair and exchange data within pair using the exchange() method of the Exchanger class. An exchanger waits until both threads call its exchange() method to exchange data.

How do threads communicate with each other in C++?

When one thread modifies a process resource, the change is immediately visible to sibling threads. Processes are independent while thread is within a process. Processes have separate address spaces while threads share their address spaces. Processes communicate each other through inter-process communication.


1 Answers

If you only have 2 threads accessing this resource (ie concurrent reads are not required), then the simplest (and one of the quickest) would just be to use the lock keyword:

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);
      }
    }
}

If however concurrent reads are required this would be a good fit for the ReaderWriterLockSlim class. You can acquire the read lock when copying data and the write lock when writing data eg:

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();
    }
}

Or if you are using .Net 4 or above there are many wonderful concurrently modifiable collections in the System.Collections.Concurrent namespace which you could probably use without any problem (they are lock free objects and are generally very quick - and some performance enhancements are coming in .Net 4.5 too!).

like image 183
Rich O'Kelly Avatar answered Oct 13 '22 06:10

Rich O'Kelly