C#空引用异常

时间:2011-12-27 12:15:25

标签: c# .net multithreading textbox

我正在研究以下程序,该程序处理线程和线程优先级。

我构建了一个包含富文本框(DisplayTextBox)和两个按钮的Windows窗体(用于运行应用程序的StartButton和用于关闭应用程序的ExitButton)。

在表单中,我创建了几个线程并一个接一个地运行它们。每个线程使用的方法都可以在Threading类中找到。有问题的方法是PrintOnScreen()。

在这个方法中,我将线程名称及其优先级附加到类型为StringBuilder的str。然后我想在DisplayTextBox(在Form.cs中)显示str的内容。

但是,我收到“NullReferenceException未处理:对象引用未设置为对象的实例”错误。出现错误的行如下:

DisplayTextBox.Text = Convert.ToString(str);

你能帮我解决一下这个错误吗?感谢。

修改

感谢大家的帮助。为了解决这个问题,我将PrintOnScreen方法复制到Form.cs类并丢弃了Threading.cs。

我后来使用了Anand给出的代码并将其放在t2.Join()下面。现在它就像一个魅力。

5 个答案:

答案 0 :(得分:3)

问题出现在表单的构造函数中。您再次将DisplayText声明为本地成员,以便不初始化表单的字段。像这样改变你的构造函数:

private void Form1_Load(object sender, EventArgs e)
{
    DescTextBox.Visible = false;
    DisplayTextBox = new RichTextBox();
    DisplayTextBox.Location = new Point(15, 31);
    DisplayTextBox.Height = 258;
    DisplayTextBox.Width = 303;
    panel1.Controls.Add(DisplayTextBox);
} 

它应该像你期望的那样工作。

编辑但是要注意当您想要从后台工作线程更改UI元素时会遇到的问题。在这些情况下,您将不得不使用调用模式。

答案 1 :(得分:1)

您无法与主应用程序线程之外的任何其他线程的控件进行通信。您需要使用此类收集器。看看这里:http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx

修改
@Fischermaen - 嘿,没有注意到这一点,但它仍然无法正常工作,因为这行,他写的是失败的。他仍然需要使用调度程序从非主线程

设置控件上的Text属性

编辑2
相关主题:
How to update the GUI from another thread in C#?
In WinForms, why can't you update UI controls from other threads?

答案 2 :(得分:1)

我在简单的控制台应用程序中尝试了这个,它运行正常。 问题出在DisplayTextBox上。如果要与任何控件进行交互,则必须使用UI线程或Dispatcher。 在线程类中使用以下代码, 而不是

 DisplayTextBox.Text = Convert.ToString(str);

使用这个

Dispatcher.Invoke(DispatcherPriority.Normal, 
                    new Action(
            delegate()
            {
              DisplayTextBox.Text = Convert.ToString(str);
            }
        ));

答案 3 :(得分:0)

庵。 从这里看不到,但是你遇到困难的部分原因是代码中缺少封装和糟糕的生命周期管理。

在PrintOnScreen方法中实例化str,给它一个更好的名字,不需要成为一个成员变量,根本不需要公开它。

不要使用void结果,而是返回字符串结果

e.g。

SomeTextBox = PrintOnScreen(); // (GetThreadDetails might be a better name...)

作为提示,不要混合表示和逻辑。在任何拥有它们的内部彻底保持UI控件。

不要做

public SomeType SomeName;

使它成为一个属性并给它getter和setter,即使它是简短形式

public SomeType SomeName {get;设置;}

任何其他代码都可以做一些非常愚蠢的事情,比如

Form1.SomeType = (SomeOtherType)someVar; // with appaling consequences.

任何东西都不应该有多个拥有者,任何其他路径都会导致毁灭。

PS str.ToString()是比Convert.ToString(str)更好的选择;

答案 4 :(得分:0)

嗯,这对我来说并不是很清楚你想要实现什么,但是问题是当你试图访问控件时,基本形式的Threading类继承而不被加载(窗口句柄仍然不存在)这也就是你在Form1上看不到任何内容的原因,因为你的线程输出到隐藏的形式,但没有显示。

我认为您正在尝试解决SOReader提出的线程访问问题。这不是正确的方法。