[英]Update process from within method called by backgroundworker c#
我有一個帶有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");
}
}
不幸的是,這並不成功。 一旦事件上升,我就會收到errormessage System.NullReferenceException
,它在谷歌搜索之后使我得出結論:事件事件沒有附加listerner,但是我將其附加到Backgroundworker中。
編輯:OnConsoleUpdate()== null,如下面的屏幕快照所示
該幫助程序位於另一個類文件“ helpers”中,這對於解決方案可能很重要。
我希望你們能幫助我。
歡迎來到SO!
立刻想到了幾件事。
首先,讓我們解決事件問題。 您已經找到了正確的方法-您需要一個事件和方法來調用它,但是該方法應該檢查事件是否為null
。
基本上,執行以下操作:
public event EventHandler OnConsoleUpdate;
public void ConsoleUpdate()
{
OnConsoleUpdate?.Invoke(this, EventArgs.Empty);
}
以上利用?
,一個空條件運算符。 您可以在此MSDN頁面上閱讀有關它的更多信息。
第二件事...目前尚不清楚您的后台工作者實際上是什么。 聽起來這是您創建的某種自定義類? 之所以重要,是因為.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
,否則事件不是全局事件。 因此,在一個類的一個實例中掛接到事件將不會導致該類的另一個實例“觸發”該事件。 解決問題的一種方法似乎是使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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.