2012-01-10 10 views
6

Mam aplikację jedno i dwu wątkową. Wątek 1 wysłucha danych rynkowych i zaktualizuje najnowszą ofertę dotyczącą tysięcy akcji. Wątek 2 uruchomi licznik na częstotliwości próbkowania i zrobi migawkę ostatnich cytatów do przetworzenia. Skutecznie, muszę pobrać próbkę bardzo szybkiego rynku danych rynkowych.Co to jest szybki, wydajny sposób przesyłania danych między wątkami w C#?

Moim pierwszym domysłem na rozwiązanie jest użycie BlockingQueue. Aby to zrobić, muszę przenieść funkcję licznika czasu do wątku 1, co mogę zrobić, sprawdzając zegar za każdym razem, gdy pojawi się aktualizacja wyceny i przesłać migawkę cytatów do kolejki z częstotliwością próbkowania. Obawiam się, że kolejka zużyje dużo pamięci, a wyrzucanie śmieci spowolni proces.

Moje drugie przypuszczenie polega na tym, że wątek 1 kopiuje dane do zablokowanego elementu na częstotliwości próbkowania, do której wątek 2 może uzyskać dostęp. Obawiam się, że zamki będą wolne.

Moja trójka zgaduje, że prymitywne cytaty są niestabilne. Ponieważ jeden wątek pisze tylko i jeden wątek tylko czyta, może to jest właściwe?

Czy istnieje metoda najlepszej praktyki przekazywania danych między wątkami dla tej aplikacji wrażliwej na opóźnienia? To nie jest aplikacja o bardzo wysokiej częstotliwości. Mogę tolerować opóźnienia rzędu dziesiątek ms.

Odpowiedz

7

Jeśli masz tylko 2 wątki z dostępem do tego zasobu (czyli jednoczesne odczyty nie są wymagane), a następnie najprostszych (i jeden z najszybszych) będzie tylko używać lock kluczowe:

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

Jeśli jednak wymagane są równoległe odczyty, co byłoby dobrym rozwiązaniem dla the ReaderWriterLockSlim class. Można nabyć blokadę odczytu podczas kopiowania danych i blokady zapisu podczas zapisywania danych np

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

Lub jeśli używasz .NET Framework 4 lub wyżej Istnieje wiele wspaniałych jednocześnie modyfikować kolekcje w the System.Collections.Concurrent namespace które prawdopodobnie można używać bez każdy problem (są to obiekty bez blokady i generalnie są bardzo szybkie - i some performance enhancements are coming in .Net 4.5 too!).

+0

Czy wymagana jest blokada odczytu czasu (odczyt/zapis)? :) –

+0

@AmarPalsapure Dzięki, poprawiono literówkę! –

+0

Thx za odpowiedź. Spróbuję zamków, aby zacząć. Co sądzisz o używaniu lotnych? –

0

Czy nie jest to przypadek kolejki Producent-Konsument? Konsument będzie czekał (Monitor.Wait) na producencie, aby pulsował po pojawieniu się nowego kanału. Gdy tylko pojawią się nowe/zaktualizowane kanały, producent zapełni kolejkę i uruchomi monitor Monitor.Pulse.