Home:ALL Converter>Asynchronously add value to Bindinglist/Cross-threading & Locking issue

Asynchronously add value to Bindinglist/Cross-threading & Locking issue

Ask Time:2012-09-21T22:48:58         Author:user971580

Json Formatter

I have a BindingList databound to a datgridview. I'm using it to keep track of some real-time prices. The method 'update(Quote quote)' is called multiple times a second by various threads. If the datagridview doesn't contain the Quote, it is added. If it does, the values of the quote are updated. I don't want the same quote to appear in the BindingList (or on the GUI) twice, so I tried to put a lock around the operation that checks whether the value is in the list or not. It doesn't work! What am I doing wrong? I've tried two different ways of locking, and am locking on a String object rather than just an object. The problem is definitely in the BeginInvoke(new MethodInvoker(delegate() { activeQuotes.Insert(0, quote); })); call (which is probably taking some time), but if I make that synchronous, the 'add' method throws a 'cross-threading' error. . . What can I do to avoid the cross-threading error, but ensure that the lock works also??

public BindingList<Quote> activeQuotes = new BindingList<Quote>();
object lockObject = "lockObject";

dataGridViewActive.DataSource = activeQuotes;


public void update(Quote quote)
{
//lock (lockObject)
if(Monitor.TryEnter(lockObject))
{
try
   {
    if (!activeQuotes.Contains(quote))
    {
       try
       {
          activeQuotes.Add(quote);
          AddQuote(quote);
       }
       catch (Exception ex)
       {
          Console.WriteLine("Datagridview!!!!!!");
       }
     }
 else
 {
   int index = activeQuotes.IndexOf(quote);
   activeQuotes[index].Bid = quote.Bid;
   activeQuotes[index].Ask = quote.Ask;
   activeQuotes[index].Mid = quote.Mid;
   activeQuotes[index].Spread = quote.Spread;
   activeQuotes[index].Timestamp = quote.Timestamp;
}
finally
{
    Monitor.Exit(lockObject);
}
}

private void AddQuote(Quote quote)
{
     if (this.InvokeRequired)
     {
                BeginInvoke(new MethodInvoker(delegate() { activeQuotes.Insert(0, quote); }));
                BeginInvoke(new MethodInvoker(delegate() { dataGridViewActive.Refresh(); }));
                BeginInvoke(new MethodInvoker(delegate() { dataGridViewActive.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); }));
    }
    else
    {
                activeQuotes.Add(quote);
                dataGridViewActive.Refresh();
                dataGridViewActive.AutoResizeColumns (DataGridViewAutoSizeColumnsMode.AllCells);
     }
}

I'd appreciate any help at all on this.

Thanks.

Author:user971580,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/12532877/asynchronously-add-value-to-bindinglist-cross-threading-locking-issue
yy