C#螺纹问题
为了处理线程、代理和后台工作人员,我正在组装一些小应用程序,其中一个有点麻烦。 我有一个Windows窗体,有一个文本框、一个按钮和一个richttext。 当我按下按钮时,文本框中的文本被用作实例化类的参数,如下所示:C#螺纹问题,c#,multithreading,backgroundworker,C#,Multithreading,Backgroundworker,为了处理线程、代理和后台工作人员,我正在组装一些小应用程序,其中一个有点麻烦。 我有一个Windows窗体,有一个文本框、一个按钮和一个richttext。 当我按下按钮时,文本框中的文本被用作实例化类的参数,如下所示: public partial class Form1 : Form { private BackgroundWorker backgroundWorker; public Form1() { InitializeComponent();
public partial class Form1 : Form
{
private BackgroundWorker backgroundWorker;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(worker_DoWork);
backgroundWorker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
new Thread((ThreadStart)delegate()
{
this.BeginInvoke((ThreadStart)delegate()
{
foreach (string line in textBox1.Lines)
{
Dig digger = new Dig(line, textBox1.Text);
digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
string response = digger.GetAllInfo();
richTextBox1.AppendText(response);
Application.DoEvents();
}
});
}).Start();
}
void OnUpdateTicker(string msg)
{
new Thread((ThreadStart)delegate()
{
this.BeginInvoke((ThreadStart)delegate()
{
label4.Text = msg;
Application.DoEvents();
});
}).Start();
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (string line in textBox1.Lines)
{
Dig digger = new Dig(line, textBox1.Text);
digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
string response = digger.GetAllInfo();
richTextBox1.Invoke((Action) delegate { richTextBox1.AppendText(response); });
}
}
调试时,我遇到一个'textBox1.Lines'抛出了一个类型为“Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessaginException”的异常
关于如何解决这个问题有什么建议吗?首先,不需要在
DoWork
中创建新线程;BackgroundWorker
的整体思想是在一个单独的线程上执行DoWork
。其次,由于DoWork
在单独的线程上执行,并且只能在UI线程上修改UI控件,因此需要正确调用这些更新。因此,worker\u DoWork
的重写版本可能如下所示:
public partial class Form1 : Form
{
private BackgroundWorker backgroundWorker;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(worker_DoWork);
backgroundWorker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
new Thread((ThreadStart)delegate()
{
this.BeginInvoke((ThreadStart)delegate()
{
foreach (string line in textBox1.Lines)
{
Dig digger = new Dig(line, textBox1.Text);
digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
string response = digger.GetAllInfo();
richTextBox1.AppendText(response);
Application.DoEvents();
}
});
}).Start();
}
void OnUpdateTicker(string msg)
{
new Thread((ThreadStart)delegate()
{
this.BeginInvoke((ThreadStart)delegate()
{
label4.Text = msg;
Application.DoEvents();
});
}).Start();
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (string line in textBox1.Lines)
{
Dig digger = new Dig(line, textBox1.Text);
digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
string response = digger.GetAllInfo();
richTextBox1.Invoke((Action) delegate { richTextBox1.AppendText(response); });
}
}
请注意代码如何不显式生成任何新线程,以及
AppendText
方法调用如何通过控件完成。调用调用,强制它在UI线程上执行。首先,不需要在DoWork
中创建新线程;BackgroundWorker
的整体思想是在一个单独的线程上执行DoWork
。其次,由于DoWork
在单独的线程上执行,并且只能在UI线程上修改UI控件,因此需要正确调用这些更新。因此,worker\u DoWork
的重写版本可能如下所示:
public partial class Form1 : Form
{
private BackgroundWorker backgroundWorker;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(worker_DoWork);
backgroundWorker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
new Thread((ThreadStart)delegate()
{
this.BeginInvoke((ThreadStart)delegate()
{
foreach (string line in textBox1.Lines)
{
Dig digger = new Dig(line, textBox1.Text);
digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
string response = digger.GetAllInfo();
richTextBox1.AppendText(response);
Application.DoEvents();
}
});
}).Start();
}
void OnUpdateTicker(string msg)
{
new Thread((ThreadStart)delegate()
{
this.BeginInvoke((ThreadStart)delegate()
{
label4.Text = msg;
Application.DoEvents();
});
}).Start();
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (string line in textBox1.Lines)
{
Dig digger = new Dig(line, textBox1.Text);
digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
string response = digger.GetAllInfo();
richTextBox1.Invoke((Action) delegate { richTextBox1.AppendText(response); });
}
}
请注意代码如何不显式生成任何新线程,以及AppendText
方法调用如何通过控件完成。调用调用,强制它在UI线程上执行。主要原因是文本框不属于后台线程
您的UI线程拥有所有UI对象,当按下按钮时,您正在旋转一个后台线程。该后台线程不应有权访问任何UI对象
如果希望使用文本框的值,则需要以另一种方式将其传递给后台线程
主要原因是文本框不属于后台线程
您的UI线程拥有所有UI对象,当按下按钮时,您正在旋转一个后台线程。该后台线程不应有权访问任何UI对象
如果希望使用文本框的值,则需要以另一种方式将其传递给后台线程
只能从主线程本身更新主线程上的控件,除非使用控件的.Invoke方法明确告诉程序可以这样做
From: http://www.albahari.com/threading/part3.aspx
控制。调用
在多线程Windows窗体应用程序中,从创建控件的线程以外的任何线程调用控件的方法或属性是非法的。所有跨线程调用必须使用control.Invoke或control.BeginInvoke方法显式封送到创建控件的线程(通常是主线程)。人们不能依赖自动编组,因为它发生得太晚了——只有当执行深入到非托管代码中时,此时大量的内部.NET代码可能已经在“错误”线程上运行了——这些代码不是线程安全的。您只能从主线程本身更新主线程上的控件,除非您使用控件的.Invoke方法明确告诉您的程序可以这样做
From: http://www.albahari.com/threading/part3.aspx
控制。调用
在多线程Windows窗体应用程序中,从创建控件的线程以外的任何线程调用控件的方法或属性是非法的。所有跨线程调用必须使用control.Invoke或control.BeginInvoke方法显式封送到创建控件的线程(通常是主线程)。人们不能依赖自动编组,因为它发生得太晚——只有当执行顺利进入非托管代码时,此时大量内部.NET代码可能已经在“错误”线程上运行了——这些代码不是线程安全的