我是C#的新手,我正在尝试围绕面向对象的编程。这就是我想要完成的事情:
我有一个带有Form1的Windows窗体应用程序和一个名为connect(相同命名空间)的单独类。
我理解在执行大量代码时使用后台工作人员是一种好习惯(以免冻结UI)。所以我在Form1中创建了一个后台工作程序和一个progresschanged句柄。我试图找到如何在单独的连接类中触发progresschange。在Form1的progresschange块中,我有一个case / switch,用于确定屏幕上显示的文本。
最好的方法是什么?我可以把背景工作者传给另一个班级吗?
答案 0 :(得分:5)
您也可以将BackgroundWorker放在Connect类中。在这个课程中,您可以创建事件以将进度和完成情况报告回调用表单。
using System;
using System.ComponentModel;
namespace WindowsTest
{
public class Connect
{
BackgroundWorker bw;
public Connect()
{
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.DoWork +=new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
}
public delegate void ProgressChangedHandler(Object sender, ProgressChangedEventArgs e);
public event ProgressChangedEventHandler ProgressChanged;
protected void RaiseProgressChangedEvent(ProgressChangedEventArgs e)
{
if (ProgressChanged == null)
{
return;
}
ProgressChanged(this, e);
}
public delegate void WorkCompleteEventHandler(Object sender, RunWorkerCompletedEventArgs e);
public event WorkCompleteEventHandler WorkComplete;
protected void RaiseWorkCompleteEvent(RunWorkerCompletedEventArgs e)
{
if (WorkComplete == null)
{
return;
}
WorkComplete(this, e);
}
public void Cancel()
{
if (bw.IsBusy)
{
bw.CancelAsync();
}
}
public void BeginLongRunningProcess()
{
bw.RunWorkerAsync();
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RaiseWorkCompleteEvent(e);
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
RaiseProgressChangedEvent(e);
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (ConnectToServer())
{
bw.ReportProgress(0, "Connected to server");
e.Result = LongRunningProcess();
if (e.Result.ToString() == "Cancelled")
{
e.Cancel = true;
return;
}
}
else
{
//Connection failed
e.Cancel = true;
}
}
private bool ConnectToServer()
{
//Attempt connection
return true;
}
private string LongRunningProcess()
{
int recordCount = 250;
for (int i = 0; i <= recordCount; i++)
{
if (bw.CancellationPending)
{
return "Cancelled";
}
double progress = ((double)i / (double)recordCount) * 100;
bw.ReportProgress((int)progress , "Running Process");
System.Threading.Thread.Sleep(25);
}
return "The result is 2";
}
}
}
然后在您的表单上,您只需处理事件。
namespace WindowsTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Connect connect;
private void btnConnect_Click(object sender, EventArgs e)
{
connect = new Connect();
connect.ProgressChanged += new ProgressChangedEventHandler(connect_ProgressChanged);
connect.WorkComplete += new Connect.WorkCompleteEventHandler(connect_WorkComplete);
connect.BeginLongRunningProcess();
}
private void connect_WorkComplete(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
lblStatus.ForeColor = Color.Red;
lblStatus.Text = string.Format("Status: {0}", "User Cancelled!");
return;
}
if (e.Error != null)
{
//Process exception
lblStatus.Text = string.Format("Status: {0}", "Error!");
lblStatus.ForeColor = Color.Red;
return;
}
lblStatus.Text = string.Format("Status: Complete. {0}", e.Result);
}
private void connect_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = string.Format("Status: {0}", e.UserState.ToString());
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (connect != null)
{
connect.Cancel();
}
}
}
}
请注意,BackgroundWorker.ReportProgress()方法的第二个参数(UserState)可以传递任何对象。它不必是一个字符串。例如,如果从数据库中检索了行/行,则可以通过此方法将行传递回用户界面。对于BackgroundWorker.DoWork方法的e.Result也是如此。
埃里克
答案 1 :(得分:2)
您可以将连接类的步骤分解为单独的方法,并按顺序调用它们,如下所示。您不必从连接类对象触发progresschanged事件。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ConnectClass conObject= new ConnectClass();
backgroundWorker.ReportProgress(30, "Connecting ...");
conObject.Connect();
backgroundWorker.ReportProgress(30, "Connected."+"\n Executing query");
conObject.Execute();
backgroundWorker.ReportProgress(40, "Execution completed.");
}