我正在尝试检查是否可以在单击按钮时在文本框中显示计时器。在按钮上单击计时器应该开始运行,并在完成该过程后我想停止计时器。以下是我所拥有的。我该怎么做才能让它发挥作用?
public partial class MyClass: Form
{
public MyClass()
{
InitializeComponent();
InitializeTimer();
}
private void InitializeTimer()
{
this.timer1.Interval = 1000;
this.timer1.Tick += new EventHandler(timer1_Tick);
// don't start timer until user clicks Start
}
private void timer1_Tick(object sender, EventArgs e)
{
processingMessageTextBox.Invoke(new MethodInvoker(delegate { processingMessageTextBox.Text = "show running time after click"; }));
}
private void myButton_Click(object sender, EventArgs e)
{
this.timer1.Start();
doSomeTimeCOnsumingWork();
this.timer1.Stop();
}
}
请建议。
答案 0 :(得分:1)
有几十个错误。
MyClass
不是表单的正确名称。
在计时器事件中不需要Invoke
(如在UI线程中创建的那样),只需执行事件
private void timer1_Tick(object sender, EventArgs e)
{
processingMessageLabel.Text = "show running time after click";
}
myButton_Click
事件一次执行所有工作,阻止UI线程,使其更像这样(切换timer1
)
private void myButton_Click(object sender, EventArgs e)
{
timer1.Enabled = !timer1.Enabled;
}
还有什么?您想要执行doSomeTimeConsumingWork
吗?为什么不使用Thread
,Task
或BackgroundWorker
?
答案 1 :(得分:1)
您对doSomeTimeConsumingWork()
的调用发生在GUI线程上。 Windows窗体是单线程的 - 这意味着在doSomeTimeConsumingWork()
返回之前不会为计时器提供服务。此外,正如另一个答案所提到的,没有必要将Invoke
与Windows窗体定时器一起使用,因为它已经存在于GUI线程中。
调查System.Windows.Forms.BackgroundWorker
类,将耗时的工作放在一个单独的线程上。 BackgroundWorker
包括报告进度的机制。请参阅this MSDN article。
答案 2 :(得分:1)
我会使用其他Thread
(或BackgroundWorker
)来更新TextBox
(或Label
)与已用时间,直到工作完成。
我还会使用Stopwatch
代替Timer
(更容易获得已用时间)。
代码如下;
首先,添加此字段:
private Stopwatch sw = new Stopwatch();
现在,添加BackgroundWorker
来更新时间。
在BackgroundWorker
DoWork
事件中,请使用此代码,以使用已用时间更新相应的TextBox
或Label
:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (sw.IsRunning)
{
// Display elapsed time in seconds.
processingMessageTextBox.Invoke(new MethodInvoker(delegate { processingMessageTextBox.Text = (sw.ElapsedMilliseconds / 1000).ToString(); }));
}
}
确保您的doSomeTimeCOnsumingWork
正在另一个主题上运行,因此您不会阻止该用户界面。
您可以为此目的使用其他BackgroundWorker
,或者只使用Thread
类。
在doSomeTimeCOnsumingWork
(您可以为其创建另一个BackgroundWorker)中添加以下内容:
private void doSomeTimeCOnsumingWork()
{
sw.Reset();
sw.Start();
// Some work done here
sw.Stop();
}