从backgroundworker调用的方法内更新进程c#

时间:2017-09-29 11:05:59

标签: c# events backgroundworker updateprogress

我有一个带gui和Rich Text Box的应用程序,我输出程序当前正在做的事情,因为数据处理可能会很长。

我尝试了两种方法:

1在Backgroundworker方法中,我可以调用以下代码:

GlobalVar.backgroundWorkerAppendText = task.Build_CSV_List();
Processchange();

由于非静态上下文,我无法在助手类中使用Form1.Processchange();

2因此,我试图创建我的第一个事件处理程序 想法是helper.UpdateConsole()会引发一个事件

public event EventHandler OnConsoleUpdate;
public void Consoleupdate()
{
    OnConsoleUpdate(this, EventArgs.Empty);
}
Backgroundworker侦听的

然后从其上下文调用Processchange

public void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    StandardTasks task = new StandardTasks();
    Helper helper = new Helper();
    helper.OnConsoleUpdate += Processchange;
    task.DoSomeStuffHere()
}
public void Processchange(object sender=null, EventArgs e=null)
{
    //MessageBox.Show(GlobalVar.backgroundWorkerAppendText);
    GlobalVar.next = false;
    backgroundWorker1.ReportProgress(1);
    while (GlobalVar.next == false)
    {
        helper.TimeBreaker(100,"ms");
    }
}

不幸的是,这并不成功。一旦上升事件我得到错误消息System.NullReferenceException,在谷歌搜索之后 - 让我得出结论,没有listerner附加到事件eventhouh我附加在Backgroundworker做工作。

编辑:OnConsoleUpdate()== null,如下面的屏幕截图所示

event = null

帮助程序位于另一个类文件“helpers”中,这可能对解决方案很重要。

我希望你们能帮助我。

1 个答案:

答案 0 :(得分:2)

欢迎来到SO!

有些事情立即浮现在脑海中。

首先,让我们把事件问题排除在外。您已经获得了正确的方法 - 您需要一个事件和方法来调用它,但该方法应该检查事件是否为null

基本上,这样做:

public event EventHandler OnConsoleUpdate;
public void ConsoleUpdate()
{
    OnConsoleUpdate?.Invoke(this, EventArgs.Empty);
}

以上使用了?,一个空条件运算符。您可以阅读更多相关信息on this MSDN page

第二件事......目前还不清楚你的背景工作者究竟是什么。这听起来像是你创作的某种自定义课程?它之所以重要,是因为.NET实际上有一个BackgroundWorker类用于运行操作......好吧,在后台。它还有一个OnProgressChanged事件,您可以将其连接到可用于更新UI的事件(只需记住将WorkerReportsProgress属性设置为true)。要使用上面提到的BackgroundWorker,您不需要创建自己的任何事件。

以下是如何使用标准.NET BackgroundWorker

System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();

void StartBackgroundTask()
{
    worker.DoWork += worker_DoWork;
    //if it's possible to display progress, use this
    worker.WorkerReportsProgress = true;
    worker.ProgressChanged += worker_ProgressChanged;
    //what to do when the method finishes?
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    //start!
    worker.RunWorkerAsync();
}

void worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
    //perform any "finalization" operations, like re-enable disabled buttons
    //display the result using the data in e.Result
    //this code will be running in the UI thread
}

//example of a container class to pass more data in the ReportProgress event
public class ProgressData
{
    public string OperationDescription { get; set; }
    public int CurrentResult { get; set; }
    //feel free to add more stuff here
}

void worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    //display the progress using e.ProgressPercentage or e.UserState
    //this code will be running in the UI thread
    //UserState can be ANYTHING:
    //var data = (ProgressData)e.UserState;
}

void worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    //this code will NOT be running in the UI thread!
    //you should NOT call the UI thread from this method

    int result = 1;
    //perform calculations
    for (var i = 1; i <= 10; i++)
    {
        worker.ReportProgress(i, new ProgressData(){ OperationDescription = "CustomState passed as second, optional parameter", CurrentResult = result });
        System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
        result *= i;
    }

    e.Result = result;
}

现在,关于BackgroundWorker类的事情是它相当陈旧,使用当前的.NET版本,您可以使用async / await关键字轻松处理后台操作和UI更新,但这可能超出了这个问题的范围。也就是说,async / await的存在并没有使BackgroundWorker的使用无效,这在使用上非常简单。

您的代码中还有一件令人担忧的事情。

public void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    StandardTasks task = new StandardTasks(); //<- you create a task
    Helper helper = new Helper(); // <- you create a helper
    helper.OnConsoleUpdate += Processchange; // <- you hook up to the helper event
    task.DoSomeStuffHere(); // <- you do stuff with the task... but the task doesn't know about your helper above! Does `StandardTasks` use `Helper`? If so, how?
}

请注意,事件除非static,否则不是全局的。因此,在一个类的一个实例中连接到一个事件不会导致该类的另一个实例“#34; fire&#34;那件事。似乎解决问题的一种方法是使StandardTasks类将Helper作为构造函数参数之一,因此代码如下所示:

Helper helper = new Helper(); // <- you create a helper
helper.OnConsoleUpdate += Processchange; // <- you hook up to the helper class event to actually do something
StandardTasks task = new StandardTasks(helper); //<- you create a task which will use the helper with the hooked up event above