我有一个带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,如下面的屏幕截图所示
帮助程序位于另一个类文件“helpers”中,这可能对解决方案很重要。
我希望你们能帮助我。
答案 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