【问题标题】:c# winform Invoke throws NullReferenceExceptionc# winform Invoke 抛出 NullReferenceException
【发布时间】:2011-06-22 02:28:41
【问题描述】:

我正在开发一个 winform(mdi) 专业版。当我从另一个线程获取新数据时,我需要更新 dataGridView 控件。当新数据出现并且我正在拖动 dataGridview 滚动时,它会在 dataGridView.Invoke 中引发空引用异常。我已经搜索了几天,让谷歌发疯,但没有帮助。 代码如下:

  
    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: 如果有新数据出现并且我没有拖动滚动条,它可以正常工作。

有什么想法吗? 谢谢!

【问题讨论】:

  • 我错过了什么吗?您似乎在内部调用ReceiveNewData。你不应该用UpdateEventArgs 做点什么,然后调用BindNewData 吗?
  • 是的,我在内部调用 ReceiveNewData。调用自身和调用 BindNewData 有什么区别吗?
  • 我想我只是误读了您的代码,抱歉。但是,您似乎没有对ex 做任何事情。它应该包含正在接收的新数据还是在其他地方处理?
  • 没有。 UpdateEventArgs 告诉我收到的是哪种类型的数据,而不是数据本身,而且我现在没有使用它。数据在两个静态列表中(QuoteMember.listOneClickQuoteItem 和 QuoteMember.listMarketingQuoteItem)

标签: c# winforms controls invoke nullreferenceexception


【解决方案1】:

我发现当您调用控件并设置绑定(或清除它们)时 并且对象设置为 null 这可能会引发 null 引用异常,这通过调用给出错误反映,但是此错误在代码中的其他位置:

快速示例:

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

它是这样的......这段代码可能不会抛出错误,因为 A)它来自我的头顶,B)它是编造的。但是,这让我困扰了半天,为什么会抛出这个错误。

只需放置

if(comboBoxEditBrand.SelectedItem == null)
  return;

这里说//错误!!它应该会再次工作。

【讨论】:

    【解决方案2】:

    确保在调用之前切换到 Gui 线程

    【讨论】:

    • orn ,如何确定?你能说得更具体点吗?
    • 在 System.Windows.Forms.Control.MarshaledInvoke(控制调用者,委托方法,对象 [] 参数,布尔同步)在 System.Windows.Forms.Control.Invoke(委托方法,对象 [] args) 在 imixClientForm.CashMarketForm.ReceiveNewData(Object sender, UpateEventArgs ex) 在 imixClientForm.ClientApplication.UpdateData(UpateEventArgs e) 在 imixClientForm.ClientApplication.onMessage(Data message, SessionID sessionID)
    • True @SLaks,我想我是在 BeginInvoke vs Invoke,这是一个很好的讨论/答案 - stackoverflow.com/questions/229554/…
    • -1,因为 InvokeRequired/Invoke 用于另一个线程的上下文中,以完全按照您告诉他的方式执行... Invoke 已经用于此目的:将要执行的方法排队在 GUI 线程的上下文中。见文档:msdn.microsoft.com/en-us/library/…
    • @Miguel Angelo,我编码对吗?我错过了什么可能会导致问题吗?
    猜你喜欢
    • 1970-01-01
    • 2013-05-30
    • 2020-11-17
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多