【发布时间】:2014-07-24 03:43:21
【问题描述】:
我创建了一个带有 button1 的 form1 来启动一个任务,它将在后台使用 BackGroundWorker 在一个单独的类上进行处理,并在一个单独的窗口上显示一个 ProgressBar。
我的问题是进程运行正常,只是任务完成但进度条形式挂在中间。
下面是BackGroundLoading类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
namespace sample2
{
public class BackgroundLoading
{
public BackgroundWorker Bw;
public delegate void RunFunction();
public RunFunction thisFunction;
mycontrols.LoadProgress p = new mycontrols.LoadProgress();
public BackgroundLoading(RunFunction newFunction)
{
thisFunction = newFunction;
Bw = new BackgroundWorker();
Bw.WorkerReportsProgress = true;
Bw.DoWork += new DoWorkEventHandler(Bw_DoWork);
Bw.ProgressChanged += new ProgressChangedEventHandler(Bw_ProgressChanged);
Bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Bw_RunWorkerCompleted);
}
public void Start()
{
Bw.RunWorkerAsync();
}
void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("Error: " + e.Error.Message);
}
if (e.Cancelled)
{
MessageBox.Show("Cancelled!");
}
else
{
MessageBox.Show("Completed!");
p.Close();
}
}
public void Bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
/// If I put
/// p.ProgBar.Value = e.ProgressPercentage;
/// the progressbar hangs upon form show.
}
void Bw_DoWork(object sender, DoWorkEventArgs e)
{
p.Show();
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 100); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
if (thisFunction != null)
{
thisFunction();
worker.ReportProgress((i * 1));
p.ProgBar.Value = i;
}
else
{
MessageBox.Show("Error, no method found");
}
}
}
}
}
}
这是 Form1 代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace sample2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
BackgroundLoading BL = new BackgroundLoading(workingmethod);
BL.Start();
}
private void workingmethod()
{
System.Threading.Thread.Sleep(10);
}
}
}
这是 LoadProgress 表单的代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace sample2.mycontrols
{
public partial class LoadProgress : Form
{
public LoadProgress()
{
InitializeComponent();
}
private void LoadProgress_Load(object sender, EventArgs e)
{
}
}
}
进度条表单上没有代码,因为更新是在类上完成的。 找不到挂起的原因。
提前致谢。
【问题讨论】:
-
您是否尝试过将
p.Show();移出Bw_DoWork事件处理程序(BackgroundLoading ctor 可能会起作用)?不应从后台线程访问 WinForms 控件(DoWork 在非 UI 后台线程上触发)。从 UI 线程以外的任何线程访问 Form 或 UserControl 属性会导致不可预知的行为 -p.ProgBar.Value = i;也是如此(您可以在正确编组到 UI 线程的 ProgressChanged 事件中更新它) -
您是否尝试过调试您的代码?
-
您正在从非 UI 线程访问 UI。改用 Invoke():
p.Invoke(new MethodInvoker(delegate { p.ProgBar.Value = e.ProgressPercentage; }));
标签: c# winforms class progress-bar backgroundworker