C# 定时器不工作';由于用户界面无响应,无法正常工作
从SQL存储过程中执行数据提取的C#窗口不会显示“已用时间”,因为计时器控件似乎不起作用 我的一个应用程序使用定时器控制,它在处理时似乎不能保持定时器的滴答声 如果我在Form\u Load上执行C# 定时器不工作';由于用户界面无响应,无法正常工作,c#,winforms,timer,C#,Winforms,Timer,从SQL存储过程中执行数据提取的C#窗口不会显示“已用时间”,因为计时器控件似乎不起作用 我的一个应用程序使用定时器控制,它在处理时似乎不能保持定时器的滴答声 如果我在Form\u Load上执行Timer.Start(),它似乎工作正常。但是,在开始数据提取(大约需要2-3分钟)之前的Timer.Start()似乎不起作用 计时器已启用 private void btnCalculate_Click(object sender, EventArgs e) { tmrTime.Start
Timer.Start()
,它似乎工作正常。但是,在开始数据提取(大约需要2-3分钟)之前的Timer.Start()
似乎不起作用
计时器已启用
private void btnCalculate_Click(object sender, EventArgs e)
{
tmrTime.Start();
if (txtEmployeeNumber.Text.Trim() != "")
{
dtStart = DateTime.Now;
connectDB(); //Connects to Database, Executes a Stored Procedure, Prepares a response String, and assigns response to a Textbox. All of which takes 2-3 minutes.
}
else
{
MessageBox.Show("Please enter a value!");
}
tmrTime.Stop();
}
private void tmrTime_Tick(object sender, EventArgs e)
{
txtTimer.Text = "Time Elapsed : " + (DateTime.Now - dtStart).Seconds + " second(s)";
}
也许更好的解决办法是使用秒表? 请点击此处: 编辑: 在史蒂夫的评论之后,我为秒表类添加了一些可用性
static void Main(string[] args)
{
var sw = new Stopwatch();
sw.Start();
DoSomething();
sw.Stop();
Console.WriteLine($"DoSomething() code took {sw.ElapsedMilliseconds}ms to run.");
sw.Restart();
DoSomethingElse();
sw.Stop();
Console.WriteLine($"DoSomethingElse() code took {sw.ElapsedMilliseconds}ms to run.");
}
注意-调试时请注意奇怪的计算-当您在代码中的点上放置断点时,它将继续计数。应该这样做
var sw = Stopwatch.StartNew();
// here execute your DB call
sw.Stop();
txtTimer.Text = string.Format("Time Elapsed : {0}", sw);
现在,如果您通过后台线程执行此操作,您的屏幕应该会有响应。只需确保同步控件(文本框)。您可以从BackgroundWorker
开始,然后在DoWork
上执行此操作。完成后,读取数据并设置控制值
更新
如果您想在表单上显示执行时间,请执行此操作。这就是你所需要的
public partial class Form1 : Form
{
Timer _timer = new Timer();
private DateTime _startTime;
public Form1()
{
InitializeComponent();
_timer.Interval = 1000;
_timer.Tick += _timer_Tick;
}
void _timer_Tick(object sender, EventArgs e)
{
var span = (DateTime.Now - _startTime);
label1.Text = string.Format("Elapsed: {0}", span);
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "";
_startTime = DateTime.Now;
_timer.Start();
var bgw = new BackgroundWorker();
bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;
bgw.DoWork += bgw_DoWork;
bgw.RunWorkerAsync();
}
void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_timer.Stop();
}
void bgw_DoWork(object sender, DoWorkEventArgs e)
{
// run query here
}
}
在您的按钮代码中,如果在IF块之后启动计时器,您不是立即停止计时器吗?您使用的是什么类型的计时器?那么您应该使用BackgroundWorker(类)及其ProgressChanged-事件来更新计时器/GUI。缓慢的数据库查询不能挂起UI线程。使用工作线程代替任务或BackgroundWorker类。如果您的员工一次只能按照给定的顺序做一件事,那么他们在忙于处理数据库时,自然不能从1数到N。众所周知,在windows编程中,任何不能快速返回的内容都不应该出现在主线程上(因为UI共享它)。如果长时间运行的进程只是您的应用程序在等待对代码库之外的某些内容(如远程API调用)的响应,那么您不需要后台线程,您可以使用异步编程。也许更好的答案可以说明如何在这种情况下使用秒表?好的,但是我认为OP想要用它的代码显示某种计时器的进度。你不能用秒表做这件事。虽然不是我的否决票。我也没有否决票,但这仍然会阻止UI线程(注意这是在
单击事件中发生的),我不认为这是OP真正想要的。我认为他们希望在长期运作期间取得一些进展。有点像进度条。这样,您只给出操作所需的总时间。没有人在谈论报告记录数。我从这个问题中推测,他希望不断看到文本框中的计时器滴答作响。但是因为DB调用阻塞了线程,他看不到时间增量。@Camiloteriento这与问题无关。底线是,执行和显示的独立线程。如果我有时间写的话,我可以使用ThreadPool
。BGWorker是表达需要做什么的简单方法。此外,OP是否仍在FW3.5中?事实上,我使用了现有的项目,即FW3.5-)enjoy@T.S.OP没有CPU限制的工作要做,所以不,这也不合适。创建后台线程或线程池线程不应该只是为了让它无所事事,就像让UI线程那样。@t.S.不,这是错误的。UI线程不需要阻塞。这并不意味着您需要创建一些其他线程来在整个时间内什么都不做。正确的做法是异步执行工作,这样就不会阻塞任何线程。不使用任何非UI线程就可以轻松解决此类问题。你不明白这表明你不应该回答这类问题。