naw*_*fal 3 .net c# timer c#-4.0
什么应该直截了当不在这里,尽管阅读了很多,我还是找不到办法.
我有一个执行耗时功能的按钮.因此,单击该按钮应显示间隔为500毫秒的标签中经过的时间(以毫秒为单位).当达到预期的结果时,我希望计时器停止.我不需要标签中的最终时间(消耗的总时间),但标签应该动态显示经过的时间.我的代码是:
private void btnHistory_Click(object sender, EventArgs e)
{
Class1 c = new Class1();
c.StartClock(ref label12);
Utility.PopulateHistory(dgvRecords_history, _util); //time consuming function
c.StopClock();
}
Run Code Online (Sandbox Code Playgroud)
在Class1我写这个:
internal void StartClock(ref Label l)
{
Timer t = new Timer();
t.Interval = 500;
t.Enabled = true;
t.Tag = l;
t.Tick += new EventHandler(t_Tick);
t.Start();
}
int i;
bool stop;
void t_Tick(object sender, EventArgs e)
{
if (stop)
{
((Timer)sender).Stop();
return;
}
((Label)((Timer)sender).Tag).Text = (++i).ToString();
}
internal void StopClock()
{
i = 0;
stop = true;
}
Run Code Online (Sandbox Code Playgroud)
发生的事情是,t_Tick只有在按钮事件下的完整代码被触发后才会触发事件.这是tick事件在通过StopClock函数后触发!我不知道为什么它应该是那个!
基本上有2个问题
如何以正确的方式实现我的要求?我知道我应该使用其他内置类来评估性能,但这仅用于显示目的.为此,理想的方法是什么?
为什么我的代码不起作用?
编辑:我在System.Windows.Forms Timer这里使用过,但结果没有任何不同System.Timers Timer
问题是您的长时间运行任务也在UI线程上运行.因此,计时器无法触发并更新UI,因为线程正忙于处理长时间运行的任务.
相反,您应该使用BackgroundWorker来处理长时间运行的任务.
在代码中:
private void btnHistory_Click(object sender, EventArgs e)
{
Class1 c = new Class1(ref label12);
c.StartClock();
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s, e) =>
{
// time consuming function
Utility.PopulateHistory(dgvRecords_history, _util);
};
backgroundWorker.RunWorkerCompleted += (s, e) =>
{
c.StopClock();
};
backgroundWorker.RunWorkerAsync();
}
Run Code Online (Sandbox Code Playgroud)
正如ChrisWue所指出的,由于您现在在一个单独的线程中拥有长时间运行的任务,因此需要调用对UI线程上的UI控件的任何访问.
如果长时间运行的任务只需要UI中的某些数据启动,则可以将该数据作为参数传递RunWorkerAsync().如果需要将一些结果数据输出到UI,则可以在RunWorkerCompleted事件的处理程序中执行此操作.如果您偶尔需要在进行更新时更新UI,则可以在ProgressChanged事件的处理程序中执行此操作,并ReportProgress()在DoWork处理程序中调用.
如果不需要上述任何一项,您可以使用ThreadPool,如StaWho的答案.