Muszę utworzyć interfejs użytkownika WPF, który subskrybuje aktualizacje w czasie rzeczywistym Fx Rate (Currency + rate) i wyświetla je w siatce (około 1000 aktualizacji na sekundę, co oznacza, że każdy wiersz w tabeli może uzyskać zaktualizowano upto 1000 razy na sekundę). Siatka miała co najmniej 50 rzędów w dowolnym momencie.Aktualizowanie interfejsu użytkownika w czasie rzeczywistym
W tym celu utworzyłem Viewmodel, który subskrybuje zdarzenia aktualizacji i zapisuje te aktualizacje w współbieżnym słowniku z kluczem jako symbolem i wartością jako obiekt RateViewModel. Następnie mam kolejną obserwowalną kolekcję, która ma wszystkie obiekty rateviewmodel i wiąże ją z siatką.
Kod:
public class MyViewModel
{
private readonly IRatesService ratesService;
private readonly ConcurrentDictionary<string, RateViewModel> rateDictionary;
private object _locker = new object();
public MyViewModel(IRatesService ratesService)
{
this.ratesService = ratesService;
this.ratesService.OnUpdate += OnUpdate;
rateDictionary = new ConcurrentDictionary<string, RateViewModel>();
RateViewModels = new ObservableCollection<RateViewModel>();
}
private void OnUpdate(object sender, RateUpdateEventArgs e)
{
RateViewModel exisistingRate;
if (!rateDictionary.TryGetValue(e.Update.Currency, out exisistingRate))
{
exisistingRate = new RateViewModel(new Rate(e.Update.Currency, e.Update.Rate));
rateDictionary.TryAdd(e.Update.Currency, exisistingRate);
return;
}
lock (_locker)
{
exisistingRate.UpdateRate(e.Update.Rate);
}
Application.Current.Dispatcher.BeginInvoke(new Action(() => SearchAndUpdate(exisistingRate)));
}
public ObservableCollection<RateViewModel> RateViewModels { get; set; }
private void SearchAndUpdate(RateViewModel rateViewModel)
{
//Equals is based on Currency
if (!RateViewModels.Contains(rateViewModel))
{
RateViewModels.Add(rateViewModel);
return;
}
var index = RateViewModels.IndexOf(rateViewModel);
RateViewModels[index] = rateViewModel;
}
}
Mam 4 pytania o to:
Czy istnieje sposób mogę wyeliminować ObservableCollection, ponieważ to prowadzi do 2 różnych datastructures przechowujących te same elementy - ale nadal moje aktualizacje są przekazywane do interfejsu użytkownika?
Użyłem słownika równoczesnego, który prowadzi do zablokowania całej operacji aktualizacji. Czy istnieje jakaś inna sprytna metoda radzenia sobie z tym, zamiast blokowania całej bazy danych lub jakiejkolwiek bazy danych?
Moja metoda UpdateRate również blokuje się - wszystkie moje właściwości na moim RateviewModel są tylko do odczytu, z wyjątkiem ceny, ponieważ jest ona aktualizowana. Czy istnieje sposób na uczynienie tego atomowego, proszę zauważyć, że cena przychodzi jako podwójna.
Czy istnieje sposób, aby zoptymalizować metodę SearchAndUpdate, jest to związane z 1st. W tej chwili uważam, że jest to operacja O (n).
Korzystanie .NET 4.0 i pominięto INPC dla zwięzłości.
* EDYCJA: * Czy mógłbyś mi pomóc w lepszym przepisaniu tego, biorąc pod uwagę wszystkie 4 punkty? Psuedocode to zrobi.
Dzięki, -Mike
Czy możesz umieścić jakiś pseudo kod do punktu 3, proszę? – Mike
Nie jestem do końca jasny o tym "Użyj Interlocked.CompareExchange, aby ustawić prywatne pole na 1, jeśli to zwróci 1 wyjście, ponieważ wciąż jest oczekująca aktualizacja interfejsu użytkownika Jeśli Interlocked.CompareExchange zwróciło 0, wywołaj interfejs użytkownika i zwolnij właściwość zmieniła wydarzenie i zaktualizuje pole dławienia do 0 (technicznie jest więcej, co musisz zrobić, jeśli zależy ci na x86) "--- Czy możesz zamieścić krótki fragment kodu? – Mike
@Mike Dodałem kod pokazujący technikę – Yaur