我正在编写一个应用程序,需要在加载数据库时更新状态栏。我将标签设置为“Database loading ...”,然后使用BackgroundWorker
加载数据库。当worker完成时,我将标签设置为“Database loaded”。但是,这仅在启动时完成,我不希望标签显示更长时间,并且希望在工作完成后几秒钟清除它。我可以在我的main上放置一个专用的计时器对象,但是这个单一动作将是它唯一的工作,而且似乎应该存在一个更优雅的解决方案。所以我尝试了lambdas:
void dataLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DataLabel.Text = "Database Loaded";
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 5000;
timer.Tick += new EventHandler((o, a) =>
{
DataLabel.Text = "";
(o as System.Windows.Forms.Timer).Enabled = false;
});
}
当然timer
的范围在函数退出后到期,并且永远不会调用Tick
事件。
如何在不使用全局实例计时器的情况下运行简单的单火事件?
答案 0 :(得分:2)
也许您可以在其正文中使用Thread.Sleep(N)的某些方法的异步调用。
答案 1 :(得分:2)
你的代码很好。事实上,在我看来,您的通用架构是最优雅的解决方案。你只是忘了启动计时器。您不必担心GC过早地收集计时器,因为它在启动时会自动“自动”生成。这当然会引发一个问题,即这是否会导致内存泄漏,因为每次都会创建一个新的计时器。我想不是因为定时器在停止时也会“自根”。所以以下应该可以正常工作。
void dataLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DataLabel.Text = "Database Loaded";
var timer = new System.Windows.Forms.Timer();
timer.Interval = 5000;
timer.Tick += (o, a) =>
{
timer.Stop();
DataLabel.Text = "";
};
timer.Start();
}
答案 2 :(得分:1)
您可以创建一个类变量Timer
,只需使用一次,然后使用null
。
此外,您可以使用ThreadPool注册一个方法 - 在此线程中,在触发对UI的调用以更新标签之前,睡眠所需的数量。
或者您可以重复使用后台工作程序以获得相同的效果。这样就可以节省您在UI线程上的Control.Invoke
...
答案 3 :(得分:0)
通常,即使在Visual Studio中,状态仍然存在,直到用户执行其他操作。这似乎是一种更好的方法,因为用户可能无法在5秒或10秒内检查状态。我认为最好在使用时更新状态(如点击菜单等)
答案 4 :(得分:0)
你可能只是让后台线程等待一段时间,例如:
void dataLoader_DoWork(object sender, DoWorkEventArgs e) {
// Do work normally.
// Report progress as complete.
var worker = sender as BackgroundWorker;
worker.ReportProgress(100);
Thread.Sleep(5000);
}
void dataLoader_ProgressChanged(object sender, ProgressChangedEventArgs e) {
if (e.ProgressPercentage == 100) {
// Set label here
DataLabel.Text = "Database Loaded";
}
}
void dataLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DataLabel.Text = "";
}
这可能比触发异步方法好一点,因为已经为后台工作者创建了一个线程。这会更好吗?
答案 5 :(得分:0)
在ThreadPool中对WorkItem进行排队,睡眠5秒,然后BeginInvoke
更新行为。这是一个基本的例子:
using System;
using System.Threading;
using System.Windows.Forms;
namespace CSharpScratch
{
class Program
{
private static void Main()
{
var myForm = new MyForm();
myForm.ShowDialog();
}
}
class MyForm : Form
{
private readonly Label _label;
public MyForm()
{
_label = new Label {Text = "Hello", Parent = this};
Load += FormLoaded;
}
public void FormLoaded(object sender, EventArgs args)
{
ThreadPool.QueueUserWorkItem(x =>
{
Thread.Sleep(5000);
BeginInvoke(new Action(() => _label.Text = "Goodbye"));
});
}
}
}