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 上阅读有关线程的信息:)