alexander
alexander

Reputation: 195

LINQ and the dynamic List Type

Have class:

public class SignalRounding
{
    public DateTime LastUpdated { get; set; }
    public int Quantity { get; set; }
    public string symbol { get; set; }
    public double price { get; set; }
    public double round { get; set; }
}
public class SignalRoundingView
{
    public DateTime LastUpdated { get; set; }
    public int Quantity { get; set; }
    public string symbol { get; set; }
    public double price { get; set; }
    public double round { get; set; }
}

Create list

public static List<SignalRounding> SignalR;
SignalR = new List<SignalRounding>();
ListView.ItemsSource = SignalR;
ListView.Items.Refresh();

Add some information with certain parameters

try
{
 var r = SignalR.Where(t => t.LastUpdated >= DateTime.Now.AddMinutes(-10))
 .GroupBy(g => g.symbol)
 .Select(s => new SignalRoundingView()
  {
    LastUpdated = s.Max(x => x.LastUpdated),
    Quantity = s.Count(),
    symbol = s.Key,
    price = s.Single(l => l.LastUpdated == s.Max(x => x.LastUpdated)).price,
    round = s.Single(l => l.LastUpdated == s.Max(x => x.LastUpdated)).round
  })
.OrderByDescending(x => x.LastUpdated)
.ThenByDescending(x => x.Quantity).ToList();

Filter3List.ItemsSource = r;
Filter3List.Items.Refresh();
}
catch (Exception){throw;}

List<SignalRounding> SignalR is dynamic - sometimes there is an error. With the following description: Collection was modified; the operation cannot be performed enumerating.

How fix it?

Upvotes: 0

Views: 187

Answers (2)

Carl
Carl

Reputation: 998

Make sure you don't allow one thread to iterate over the list (Linq query) while another thread is adding to it. You can use a lock to achieve this. There's a performance penalty so you need to decide whether this solution works well enough for you depending on how fast you add new objects to the list and how long the list gets.

private object myLock = new Object();

void AddToList(SignalR s)
{
    lock(myLock) {
        SignalR.Add(s);
    }
}

void UpdateList() {
    lock(myLock)
    {
        var r = SignalR.Where(...).ToList();

        Filter3List.ItemsSource = r;
        Filter3List.Items.Refresh();
    }
}

Upvotes: 1

DavidG
DavidG

Reputation: 118937

You have multiple threads accessing your list which will throw exceptions. Instead of List<T>, use ConcurrentBag<T>:

public static ConcurrentBag<SignalRounding> SignalR;

Note: This is in the System.Collections.Concurrent namespace.

Upvotes: 1

Related Questions