簡體   English   中英

從backgroundworker c#調用的方法內部更新過程

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM