[英]null reference problems with c#
在我的一种窗口形式中,我创建了一个类的实例,以在后台执行一些工作。 我想捕获该类中的调试消息,并显示在窗口形式的文本框中。 这是我所做的:
class A //window form class
{
public void startBackGroundTask()
{
B backGroundTask = new B(this);
}
public void updateTextBox(string data)
{
if (data != null)
{
if (this.Textbox.InvokeRequired)
{
appendUIDelegate updateDelegate = new appendUIDelegate(updateUI);
try
{
this.Invoke(updateDelegate, data);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
else
{
updateUI(data);
}
}
}
private void updateUI(string data)
{
if (this.Textbox.InvokeRequired)
{
this.Textbox.Invoke(new appendUIDelegate(this.updateUI), data);
}
else
{
//update the text box
this.Textbox.AppendText(data);
this.Textbox.AppendText(Environment.NewLine);
}
}
private delegate void appendUIDelegate(string data);
}
class B // background task
{
A curUI;
public b( A UI)
{
curUI = UI;
}
private void test()
{
//do some works here then log the debug message to UI.
curUI.updateTextBox("message);
}
}
我不断收到空引用异常
this.Invoke(updateDelegate, data);
叫做。
我知道传递“ this”作为参数很奇怪,但是我想将调试消息发送到我的窗口表单。
两件事情:
1)考虑使用扩展方法,这样您就不会在所有这些调用上重复自己:
public static class ControlExtentions
{
public delegate void InvokeHandler();
public static void SafeInvoke(this Control control, InvokeHandler handler)
{
if (control.InvokeRequired)
control.Invoke(handler);
else
handler();
}
}
2)考虑使用事件使其更具可读性。 使用如下设计:
class B
{
public event EventHandler LogGenerated = delegate { };
void test()
{
LogGenerated("Some log text", EventArgs.Empty);
}
}
class A : Control
{
public A()
{
B b = new B();
b.LogGenerated += new EventHandler(b_LogGenerated);
}
void b_LogGenerated(object sender, EventArgs e)
{
this.SafeInvoke(() => { textBox1.Text += (String)sender; });
}
}
不要让调用SafeInvoke的语法给您带来太多麻烦。 它只是代表InvokeHandler委托的lambda。
您在问题中描述的逻辑不会产生空引用异常,这表明该异常来自您正在执行的后台任务,而不是来自UI更新逻辑。
作为证据,这是一个完整的示例,可以简化,但基于您描述的模式:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void updateTextBox(string data)
{
if (this.textBox1.InvokeRequired)
{
this.Invoke(new MethodInvoker(() => updateTextBox(data)));
return;
}
if (data == null)
{
return;
}
//update the text box
this.textBox1.AppendText(data);
this.textBox1.AppendText(Environment.NewLine);
}
private void _uxStartBgTask_Click(object sender, EventArgs e)
{
new Thread(() => updateTextBox("message")).Start();
}
}
请注意,使用MethodInvoker无需声明委托成员,并且立即递归是解决InvokeRequired模式的便捷方法。
看来您有一个无限循环。 updateTextBox构造一个用于调用updateUI的委托,而updateUI构造一个用于updateUI的委托。 是什么在这里阻止无限递归?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.