windows 表单应用程序中的后台工作人员
Background worker in windows form application
我有以下星座:
MainForm.cs -> 包括我所有的表单元素
Program.cs -> 包括主要部分,这是一个 xmlreader/writer 来改变 xml 文件中的 xml 属性,这些文件可以大到 4gb[=12] =]
所以这个小应用程序可以工作,但当然 UI 变得无响应和冻结,我想避免这种情况,我也希望在途中减少这个过程的持续时间
我从 BtnClick 事件开始调用 xmlread/write 方法:
void BtnApplyChangesClick(object sender, EventArgs e)
{
Program p = Program.Instance;
pbApplyChanges.Minimum = 0;
pbApplyChanges.Step = 1;
Cursor.Current = Cursors.WaitCursor;
foreach(DataGridViewRow cr in dataGridView2.Rows)
{
pbApplyChanges.Maximum = dataGridView2.Rows.Count;
p.changeElements(cr.Cells["Filename"].Value.ToString(), txtTenant.Text, txtDate.Text, txtEvtId2.Text);
pbApplyChanges.PerformStep();
}
Cursor.Current = Cursors.Arrow;
MessageBox.Show("Job done");
}
在调用中,我使用 Program.cs 的单例实例,那里的主要方法 (changeElements) 使用 4 个字符串参数,它们全部取自表单中的信息! (我想这是一种不好的做法,但到目前为止它有效......)
当我尝试用 backgroundWorker 替换此方法调用时(它本身进行了方法调用)我失败了,因为甚至没有进行方法调用...我发现 UI 元素可以'无法从 BW 线程访问,所以我想这也是我的方法调用不起作用的原因?!
那么我怎样才能让这个星座发挥作用呢?我是否必须将所有 4 个字符串参数和 class 实例(Program.cs 的)传递给后台工作人员? BW 是这项工作的最佳工具吗?
一般来说,BackgroundWorker 不应访问任何 UI 元素。这是 Winforms 中的一个古老建议,即访问 UI-Elements 应该只发生在 UI-Thread.
您可以像这样使用 Background-Worker:
private void Main(string[] args)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += Bw_DoWork;
bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
//Parameter you need to work in Background-Thread for example your strings
string[] param = new[] {"Text1", "Text2", "Text3", "Text4"};
//Start work
bw.RunWorkerAsync(param);
}
//Do your Background-Work
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
string[] param = e.Argument as string[];
//Process your long running task
e.Result = null; //Set your Result of the long running task
}
//Taking your results
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Apply your Results to your GUI-Elements
myTextBox1.Text = e.Result.ToString();
}
顺便说一句,Background-Worker 是一些老派的东西,所以如果您想学习新东西,请看一看 here 并了解一下 TPL。这使您可以更好地处理异步。
事实上,我认为将 4gb 数据存储在 XML-File 中并不是很好。你考虑过数据库吗?或者将 XML-文件拆分成多个 XML-文件?这样您就可以分块读取数据。
希望对您有所帮助。
我不为此使用后台工作程序。我改用普通线程。试试这个代码:
public void ButtonDoWork_Click(eventArgs......) {
DoWorkThread = new Thread(new ThreadStart(DoWork)); // Setup thread
DoWorkThread.isBackground = true; // Its background so, we need to set background flag
DoWorkThread.Start(); // Start the thread
}
private Thread DoWorkThread: // our Thread object
private void DoWork() { // This void contains action that will be performed by thread
//TODO: Background processing. To update UI from another thread use Control.Invoke(...)
}
请注意,我没有测试此代码 - 我凭记忆写了它,但它已经晚了,所以它无法工作。
您还可以在 MSDN 上阅读有关线程的信息:)
我有以下星座:
MainForm.cs -> 包括我所有的表单元素
Program.cs -> 包括主要部分,这是一个 xmlreader/writer 来改变 xml 文件中的 xml 属性,这些文件可以大到 4gb[=12] =]
所以这个小应用程序可以工作,但当然 UI 变得无响应和冻结,我想避免这种情况,我也希望在途中减少这个过程的持续时间
我从 BtnClick 事件开始调用 xmlread/write 方法:
void BtnApplyChangesClick(object sender, EventArgs e)
{
Program p = Program.Instance;
pbApplyChanges.Minimum = 0;
pbApplyChanges.Step = 1;
Cursor.Current = Cursors.WaitCursor;
foreach(DataGridViewRow cr in dataGridView2.Rows)
{
pbApplyChanges.Maximum = dataGridView2.Rows.Count;
p.changeElements(cr.Cells["Filename"].Value.ToString(), txtTenant.Text, txtDate.Text, txtEvtId2.Text);
pbApplyChanges.PerformStep();
}
Cursor.Current = Cursors.Arrow;
MessageBox.Show("Job done");
}
在调用中,我使用 Program.cs 的单例实例,那里的主要方法 (changeElements) 使用 4 个字符串参数,它们全部取自表单中的信息! (我想这是一种不好的做法,但到目前为止它有效......)
当我尝试用 backgroundWorker 替换此方法调用时(它本身进行了方法调用)我失败了,因为甚至没有进行方法调用...我发现 UI 元素可以'无法从 BW 线程访问,所以我想这也是我的方法调用不起作用的原因?!
那么我怎样才能让这个星座发挥作用呢?我是否必须将所有 4 个字符串参数和 class 实例(Program.cs 的)传递给后台工作人员? BW 是这项工作的最佳工具吗?
一般来说,BackgroundWorker 不应访问任何 UI 元素。这是 Winforms 中的一个古老建议,即访问 UI-Elements 应该只发生在 UI-Thread.
您可以像这样使用 Background-Worker:
private void Main(string[] args)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += Bw_DoWork;
bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
//Parameter you need to work in Background-Thread for example your strings
string[] param = new[] {"Text1", "Text2", "Text3", "Text4"};
//Start work
bw.RunWorkerAsync(param);
}
//Do your Background-Work
private void Bw_DoWork(object sender, DoWorkEventArgs e)
{
string[] param = e.Argument as string[];
//Process your long running task
e.Result = null; //Set your Result of the long running task
}
//Taking your results
private void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Apply your Results to your GUI-Elements
myTextBox1.Text = e.Result.ToString();
}
顺便说一句,Background-Worker 是一些老派的东西,所以如果您想学习新东西,请看一看 here 并了解一下 TPL。这使您可以更好地处理异步。
事实上,我认为将 4gb 数据存储在 XML-File 中并不是很好。你考虑过数据库吗?或者将 XML-文件拆分成多个 XML-文件?这样您就可以分块读取数据。
希望对您有所帮助。
我不为此使用后台工作程序。我改用普通线程。试试这个代码:
public void ButtonDoWork_Click(eventArgs......) {
DoWorkThread = new Thread(new ThreadStart(DoWork)); // Setup thread
DoWorkThread.isBackground = true; // Its background so, we need to set background flag
DoWorkThread.Start(); // Start the thread
}
private Thread DoWorkThread: // our Thread object
private void DoWork() { // This void contains action that will be performed by thread
//TODO: Background processing. To update UI from another thread use Control.Invoke(...)
}
请注意,我没有测试此代码 - 我凭记忆写了它,但它已经晚了,所以它无法工作。
您还可以在 MSDN 上阅读有关线程的信息:)