所以当我尝试按下“按钮2”时,我希望发生两件事a)“dowsomething”假设在“现在”类中做它的事情。 b)虽然它做了一件事,我想要它计算一下这需要多长时间。然而,因为“dosomething”是程序饥饿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();
}
答案 0 :(得分:3)
在Windows窗体中,所有UI内容都在一个线程上运行。这包括计时器 - 计时器是在幕后用Windows消息实现的。
你的问题其实是两个问题: -
如何计时取决于您所寻求的精确度。对于+/- 10ms范围内的准确度,您可以使用Environment.TickCount - 在操作之前存储它的值,然后在之后再次获取值,并减去存储的值 - 并且您有持续时间。
更准确的是System.Threading中的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/
答案 1 :(得分:2)
对于.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";
});
});
答案 2 :(得分:2)
如果您只想计算某事需要多长时间,请使用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
然而,这不会用经过的时间更新标签。
答案 3 :(得分:1)
我想我也会抛出它,虽然它不像@ 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中的主线程。