3

i'm working on an winform(mdi) pro. And I need to update a dataGridView control when i get new data from another thread. and when new data comes and i'm dragging the dataGridview scroll, it throw a nullreference exception in dataGridView.Invoke. i have searched for few days and drove google crazy,but didn't help. the code like this:

  
    public void ReceiveNewData(object sender, UpateEventArgs ex)
    {
        if (this.dataGridView.InvokeRequired)
        {
            dataGridView.Invoke(new UpateEventHandler(ReceiveNewData), new object[] { this, ex });
        }
        else
            this.BindNewData();
    }

    private void BindNewData()
     {

        if (dataGridView!= null && (QuoteMember.listOneClickQuoteItem != null || QuoteMember.listMarketingQuoteItem != null))
        {
            DataTable dataSource = PublicFunction.ToDataTable(QuoteMember.listOneClickQuoteItem);
            if (dataSource != null)
                    dataSource.Merge(PublicFunction.ToDataTable(QuoteMember.listMarketingQuoteItem), true);
                else
                    dataSource = PublicFunction.ToDataTable(QuoteMember.listMarketingQuoteItem);
            dataGridView.DataSource = dataSource;
        }
    }

public PublicFunction
{
        public static DataTable ToDataTable(List dataSource)
        {
            if(dataSource != null)
                return ToDataTable((dataSource.ToArray()), 1);
            return null;
        }

        public static DataTable ToDataTable(List dataSource) 
        {
            if (dataSource != null)
                return ToDataTable((dataSource.ToArray()), 2); 
            return null; 
        }
        private static DataTable ToDataTable(QuoteItemBase[] m, int type)
        {
            DataTable dsTemp = null;

            if (type == 1)
            {
                dsTemp = new DataTable("OneClickQuote");
            }
            else if (type == 2)
            {
                dsTemp = new DataTable("MarketingQuote");
            }
            else
                dsTemp  = new DataTable("temptable");

            dsTemp.Columns.Add("Date");
            dsTemp.Columns.Add("Time");
            dsTemp.Columns.Add("NO");
            dsTemp.Columns.Add("Name");


            if (m == null)
                return dsTemp;

            foreach (var item in m)
            {
                DataRow drTemp = dsTemp.NewRow();
                drTemp["Date"] = item.date;
                drTemp["Time"]  = item.time;
                drTemp["NO"] = item.no;
                drTemp["Name"] = item.name;
                dsTemp.Rows.Add(drTemp);

            }

            return dsTemp;
      }
}






PS: if new data comes and i'm not dragging scroll bar, it works fine.

any ideas? thank you !

peter
  • 31
  • 1
  • 3
  • Am I missing something? You seem to be invoking `ReceiveNewData` inside itself. Shouldn't you do something with `UpdateEventArgs` and invoke `BindNewData` instead? – Adam Lear Jun 22 '11 at 02:45
  • yes, i'm invoking ReceiveNewData inside itself. is there any difference between invoking itself and invoking BindNewData? – peter Jun 22 '11 at 02:51
  • I think I just misread your code there, sorry. But, It doesn't seem like you're doing anything with `ex`. Is it supposed to contain the new data being received or is that handled elsewhere? – Adam Lear Jun 22 '11 at 03:00
  • no. UpdateEventArgs is telling me which type data i received, not the data itself, And i didn't use it right now. the data is in two static list(QuoteMember.listOneClickQuoteItem and QuoteMember.listMarketingQuoteItem) – peter Jun 22 '11 at 03:20

2 Answers2

1

I found that when you invoke a control and set bindings (or clear them) and an object is set to null this can throw a null reference exception, this is reflected through invoke giving an error, this error however is somewhere else in your code:

quick example:

public class test : Form
{
  public test()
  {
    Thread t = new Thread(start);
    t.Start();
  }
  public void start()
  {
    LoadCompleteEvent();
  }
  public void LoadComplete() //fired by LoadCompleteEvent();
  {
    if(this.InvokeIsRequired)
    {
      //do invoke
      //and return
    }

    comboBoxEditBrand.Properties.Items.Clear();
    comboBoxEditBrand.Properties.Items.AddRange(ListOfStuff.ToArray());
  }
  public void comboBoxEditBrand_SelectedItemChanged(object sender, eventargs e) // fired as control is changed
  {
    //error here!!
    if(comboBoxEditBrand.SelectedItem == SomeBrandItem) //<- this is where the error is thrown!! check for null first!
    {
      //do something
    }
  }
}

it's something like this.. this code will probably not throw the error because A) it's from the top of my head and B) it's made up. BUT this is kind of what bugged me for half a morning as to WHY this error was thrown.

just place

if(comboBoxEditBrand.SelectedItem == null)
  return;

where it says //error here!! and it should work again.

jonsca
  • 10,218
  • 26
  • 54
  • 62
-1

Make sure you switch to the Gui thread before you invoke

Orn Kristjansson
  • 3,435
  • 4
  • 26
  • 40
  • orn , how to make sure? can you be more specific? – peter Jun 22 '11 at 02:39
  • at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous) at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args) at imixClientForm.CashMarketForm.ReceiveNewData(Object sender, UpateEventArgs ex) at imixClientForm.ClientApplication.UpdateData(UpateEventArgs e) at imixClientForm.ClientApplication.onMessage(Data message, SessionID sessionID) – peter Jun 22 '11 at 02:40
  • True @SLaks, I guess I was getting at BeginInvoke vs Invoke, here is a great discussion / answer - http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke – Orn Kristjansson Jun 22 '11 at 03:07
  • 1
    -1, as the InvokeRequired/Invoke are used in the context of another thread to do exactly what you told him to do... Invoke is already intended for that purpose: queue the method to be executed in the context of the GUI thread. See doc: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invoke.aspx – Miguel Angelo Jun 22 '11 at 03:13
  • @Miguel Angelo, does i code this right? did i miss something may cause the problem ? – peter Jun 22 '11 at 03:29
  • @peter: I don't see anything wrong with your code... is the NullReferenceException an inner exception of TargetInvocationException ? Maybe the code inside the `BindNewData` is throwing the real exception. – Miguel Angelo Jun 22 '11 at 03:41
  • @Miguel Angelo, InnerException is null in Exception snapshot. – peter Jun 22 '11 at 03:51