gpt4 book ai didi

c# BackgroundWorker DoWork 方法调用另一个类和 ProgressReport

转载 作者:行者123 更新时间:2023-12-02 05:34:09 25 4
gpt4 key购买 nike

我正在运行一个 BackgroundWorker 线程来完成一项耗时的任务。耗时的任务在另一个类(class)。我需要将在 BackgroundWorker 上运行的这个单独类所取得的进展传递回 Main Form1 类。我不确定如何处理这个问题。请提供建议。先感谢您。

    **// Main Form1 UI Class**    

public void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
//e.Argument always contains whatever was sent to the background worker
// in RunWorkerAsync. We can simply cast it to its original type.
DataSet ds = e.Argument as DataSet;
this.createje.ProcessData(this.ds);
}

private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Minimum = 0;
this.progressBar1.Maximum = CreateJE.max;
this.progressBar1.Value = e.Recno;
}

**//Other Class called CreateJE**

public void ProcessData(DataSet ds)
{
//Do time consuming task...
for (int i = 1; i <= 10; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);

**//How do I report progress back to the Main UI?**
//worker.ReportProgress(i * 10);
}
}
}

最佳答案

最干净、最可扩展的解决方案可能是让您的 ProcessData() 方法引发一个事件,BackgroundWorker 正在监听该事件。这样 ProcessData() 不依赖于将 BackgroundWorker 作为调用方。 (您还需要制定一种取消 ProcessData() 的方法)。如果需要,您甚至可以重新使用 ProgressChangedEventArgs。例如(未经测试,但您明白了吗?):

partial class Form1 { 
public void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) {
//e.Argument always contains whatever was sent to the background worker
// in RunWorkerAsync. We can simply cast it to its original type.
DataSet ds = (DataSet)e.Argument;
var bgw = (BackgroundWorker)sender;

var eh = new ProgressChangedEventHandler((o,a) => bgw.ReportProgress(a.ProgressPercentage));
createje.ProgressChanged += eh;
this.createje.ProcessData(this.ds));
createje.ProgressChanged -= eh; //necessary to stop listening
}

private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Minimum = 0;
this.progressBar1.Maximum = CreateJE.max;
this.progressBar1.Value = e.ProgressPercentage;
}

}

partial class CreateJE {

public event ProgressChangedEventHandler ProgressChanged;
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
var hand = ProgressChanged;
if(hand != null) hand(this, e);
}

public void ProcessData(DataSet ds)
{
for(int i = 1; i <= 10; i++)
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);

var e = new ProgressChangedEventArgs(i * 10, null);
}
}

}

快速而肮脏的方法是将 BackgroundWorker 作为参数传递给 ProcessData()。恕我直言,这是相当丑陋的,但是,将您束缚于仅使用 BackgroundWorkers,并且还强制您在一个地方(主窗体类)定义 BackgroundWorker 并在另一个地方定义 ReportProgress 的返回值(创建 JE 类)。

您还可以使用计时器并每 X 毫秒报告一次进度,查询 CreateJE 对象的进度。这似乎与您的其余代码一致。问题是它会使您的 CreateJE 类不支持多线程。

关于c# BackgroundWorker DoWork 方法调用另一个类和 ProgressReport,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11936837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com