我正在设计一个表单,我必须在同时执行操作时增加进度条(换句话说,我正在显示此操作的进度)。
此操作需要50秒。所以我使用System.Timer
来增加进度条。
我的代码中没有单个线程。当我在Timer事件处理程序中编写Progress_bar.PerformStep()
时,它会将错误称为“交叉线程操作无效”。
[从这个错误中我分析了System.Timer
必须创建一个Thread并在其中运行计时器以执行多个任务。]
我应该怎样做才能在每秒后增加进度条?
我尝试了在this问题中给出的解决方案。它删除了错误,但现在我看不到进度条增加。意味着它开始......没有增加50秒,然后是100%。
代码如下:
计时器声明(全局):
public System.Timers.Timer Thetimer = new System.Timers.Timer(1000);
事件声明(这是在构造函数中使它...错误...公开[可能不是一个正确的词]):
Thetimer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
呼叫:
Thetimer.Start();
blRetVal = FunctionToBeExecuted(parameter);
Thetimer.Stop();
事件处理程序:
void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
//StatusBar.PerformStep(); -- Tried This. It gives the Error
/* This doesn't give an error but Another issue Arises */
if (InvokeRequired)
{
BeginInvoke(new Action(StatusBar.PerformStep));
}
else
StatusBar.PerformStep();
}
P.S。我正在使用C#和Visual Studio 2008
答案 0 :(得分:4)
初始化Timers.Timer对象以与Windows窗体一起使用时,必须将timer实例的SynchronizingObject属性设置为窗体。
systemTimersTimerInstance.SynchronizingObject = this; // this = form instance。
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
答案 1 :(得分:3)
听起来你正在主线程上执行“后台”操作,这就是你调用它时进度条没有更新的原因。
答案 2 :(得分:3)
行。 Jon B是对的。你必须在一个线程中拥有长时间运行的任务,没有办法解决这个问题。简化,你这样做:
public partial class Form1 : Form
{
// ...
public System.Timers.Timer timer = new System.Timers.Timer(1000);
private void Form1_Load(object sender, EventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_elapsed);
timer.Start();
// Simulates your long running task (FunctionToBeExecuted)
// NOTE: This freezes the main UI thread for 10 seconds,
// so nothing will be drawn *at all*
Thread.Sleep(10000);
timer.Stop();
}
void timer_elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (InvokeRequired)
this.BeginInvoke(new Action(progressBar1.PerformStep));
else
progressBar1.PerformStep();
}
}
正如您在Load事件中看到的那样,您不仅要暂停进度条,还要暂停主UI线程。这对大多数用户来说是不可接受的,所有优秀的开发人员都应该在他们的工具集中有另一种选择。
围绕此方式的 方式(运行另一个进程除外)正在另一个线程中运行该任务。最简单的方法之一是使用BackgroundWorker,它非常简单。以下是您需要的更改:
public partial class Form1 : Form
{
// ...
private void Form1_Load(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Your work is completed, not needed but can be handy
// e.g. to report in some way that the work is done:
progressBar1.Value = progressBar1.Maximum;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_elapsed);
timer.Start();
// Simulates your long running task (FunctionToBeExecuted)
// Your main UI thread is free!
Thread.Sleep(10000);
timer.Stop();
}
// ...
}