c# Timer不会运行下来形成冻结
本文关键字:冻结 运行 Timer | 更新日期: 2023-09-27 18:04:21
所以当我尝试按下"button 2"时,我希望发生两件事a)"dowsomething"应该在"now"类中做它的事情。b)当它做某事时,我想让它计算某事需要多长时间。然而,因为"做某事"是程序饥饿Form1冻结,它不会运行定时器。我是c#的新手,所以我不知道如何在后台运行它。有什么新奇的想法吗?谢谢。
int time = 0;
private void button2_Click(object sender, EventArgs e)
{
timer1.Start();
nowthen now = new nowthen();
now.dosomething(withthis); //This task is program hungry and causes the form to freeze
timer1.Stop();
time = 0;
}
private void timer1_Tick(object sender, EventArgs e)
{
time = time + 1;
label2.Text = time.ToString();
label2.Refresh();
}
在Windows窗体中,所有UI内容都运行在一个线程上。其中包括定时器——定时器是在后台用windows消息实现的。
你的问题实际上是两个问题:-
- 如何在c#/Windows窗体中计时操作?
如何计时取决于你所追求的精度。对于+/- 10ms范围内的精度,您可以使用Environment。TickCount -在操作之前存储它的值,然后在操作之后再次获取值,并减去存储的值-然后您有您的持续时间。
更精确的是System中的Stopwatch类。线程-参见http://www.dotnetperls.com/stopwatch- 如何在后台运行任务?
要在后台运行操作,需要在不同的线程中运行。最简单、设计友好(但可能不是那么灵活)的方法是使用BackgroundWorker组件。这将使用工作线程为您执行操作。关于如何做到这一点,请参阅http://www.dotnetperls.com/backgroundworker。
更高级、更灵活的方法是创建自己的线程来完成这项工作。然而,这将产生一些重要的问题来考虑如何同步正在发生的事情——一旦你启动线程,你的方法调用完成(它是异步的),你需要有一个机制来通知你的UI代码进程已经完成。这个例子看起来和如何创建自己的线程一样好:http://www.daveoncsharp.com/2009/09/create-a-worker-thread-for-your-windows-form-in-csharp/对于。net 4使用:
Task.Factory.StartNew((Action) delegate()
{
// this code is now executing on a new thread.
nowthen now = new nowthen();
now.dosomething(withthis);
// to update the UI from here, you must use Invoke to make the call on UI thread
textBox1.Invoke((Action) delegate()
{
textBox1.Text = "This update occurs on the UI thread";
});
});
如果你只是想计时,使用System.Diagnostics.Stopwatch。
Stopwatch sw = Stopwatch.StartNew();
nowThen = new nowThen();
no.dosomething(withthis);
sw.Stop();
// you can get the time it took from sw.Elapsed
但是,它不会用经过的时间更新标签。
我想我也会把这个扔进去,尽管它不像@paul的解决方案那样优雅。
timer1.Start();
var bw = new BackgroundWorker();
bw.DoWork += (s, e) => { now.dosomething((myArgumentType)e.Argument); };
bw.RunWorkerCompleted += (s, e) => { timer1.Stop(); };
bw.RunWorkerAsync(withthis);
这个启动你的定时器,创建一个新的BackgroundWorker线程,告诉它在DoWork
方法中运行什么(dosomething在一个单独的线程中运行),然后在RunWorkerCompleted
方法中停止定时器(在dosomething完成后,控制返回到RunWorkerCompleted的主线程)。