我正在尝试使用后台工作程序为我的winform添加一个取消按钮。
我添加了以下语法,但文本框永远不会像我尝试实现后台工作程序之前那样更新任何进度。
public Form1()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
string resourceName = new AssemblyName(args.Name).Name + ".dll";
string resource = Array.Find(this.GetType().Assembly.GetManifestResourceNames(), element => element.EndsWith(resourceName));
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
private void btnQuery_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Iterating the array
foreach (string s in sxc)
{
txt_ProgressDetails.Visible = true;
AppendTextBoxLine("Getting Data For " + s);
//Put data into DataTable
PopulateDT(s);
}
//If the cancel button was pressed
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
private void AppendTextBoxLine(string statusMessage)
{
if (txt_ProgressDetails.Text.Length > 0)
txt_ProgressDetails.AppendText(Environment.NewLine);
txt_ProgressDetails.AppendText(statusMessage);
}
答案 0 :(得分:2)
BackgroundWorker的Do_Work事件在非STA线程中运行,您无法从那里更新UI。您可以重写代码以使用InvokeRequred
和Invoke
方法从创建它们的线程更新UI元素。
将此添加到您的表单:
delegate void UpdateUICallback(string statusMessage);
并将您的AppendTextBoxLine
方法更改为:
if (InvokeRequired)
{
UpdateUICallback d = new UpdateUICallback(AppendTextBoxLine);
this.Invoke(d, new object[] {statusMessage});
}
else
{
if (txt_ProgressDetails.Text.Length > 0)
txt_ProgressDetails.AppendText(Environment.NewLine);
txt_ProgressDetails.AppendText(statusMessage);
}
因此您的代码将如下所示:
public Form1()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
string resourceName = new AssemblyName(args.Name).Name + ".dll";
string resource = Array.Find(this.GetType().Assembly.GetManifestResourceNames(), element => element.EndsWith(resourceName));
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
};
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
private void btnQuery_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Iterating the array
foreach (string s in sxc)
{
txt_ProgressDetails.Visible = true;
AppendTextBoxLine("Getting Data For " + s);
//Put data into DataTable
PopulateDT(s);
}
//If the cancel button was pressed
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
return;
}
}
delegate void UpdateUICallback(string statusMessage);
private void AppendTextBoxLine(string statusMessage)
{
if (InvokeRequired)
{
UpdateUICallback d = new UpdateUICallback(AppendTextBoxLine);
this.Invoke(d, new object[] {statusMessage});
}
else
{
if (txt_ProgressDetails.Text.Length > 0)
txt_ProgressDetails.AppendText(Environment.NewLine);
txt_ProgressDetails.AppendText(statusMessage);
}
}