我只是想要一个不确定的进度条变得可见,并显示一些“活动”来表示查询正在运行,然后,当查询通过时,返回到不可见状态。看似简单;但使用此代码:
try
{
Cursor.Current = Cursors.WaitCursor;
progressBarChanges.Value = 50;
progressBarChanges.Step = 20;
progressBarChanges.Visible = true;
... // the meat of the code, where the query is being done, elided
} finally
{
progressBarChanges.Visible = false;
Cursor.Current = Cursors.Default;
}
...进度条永远不会显示,即使查询需要一段时间才能运行。进度条位于DGV上。我意识到我的进度代码有点蹩脚,但首先要做的事情 - 我只是希望为初学者展示某些东西。
在调用运行查询的BackgroundWorker proc之前,我将progressBar设置为可见 way :
progressBarChanges.Value = 50;
progressBarChanges.Step = 20;
progressBarChanges.Visible = true;
. . .
if (args.KeyCode == Keys.Enter)
{
if (ValidEntryForCRID(textBoxID.Text))
{
RetrieveAndBindPlatypusData();
var tb = (TextBox)Controls.Find("textBoxDuckbill", true).First();
if (tb != null)
{
tb.Focus();
}
if ((!string.IsNullOrWhiteSpace(textBoxID.Text)) &&
(backgroundWorkerShowChanges.IsBusy != true))
{
backgroundWorkerShowChanges.RunWorkerAsync();
}
. . .
...然而,progressBar永远不会变得可见(除非在为DGV的DataSource分配返回的查询/结果集的OracleDateTable值之后,我从未将其设置回visible = false)。如果我对此进行评论,那么(姗姗来迟)最终会出现,显然正在思考(错误地)“迟到总比没有好。”
有没有办法迫使Windows“注意”“progressBarChanges.Visible = true;”马上就行?类似于.ProcessMessages()或this.Refresh或...... ???
答案 0 :(得分:7)
这种情况正在发生,因为您没有给UI线程时间更新。您正在更新为可见并立即运行您的代码。代码应该在后台线程上运行并发送更新消息。
详细说明:
设置Visible属性时,UI线程实际上不会更新,直到当前逻辑结束。所以,正在发生的是:
你想要的是:
然后这个:
然后这个:
使用Task或Backgroundworker应该很容易实现。
更新代码以显示常量滚动
我相信你只是错过了进度条的样式应该是ProgressBarStyle.Marquee
。如果您已经将工作卸载到后台工作人员,那么剩下的工作就应该正常工作
public Form1()
{
InitializeComponent();
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
progressBar1.Enabled = progressBar1.Visible = false;
progressBar1.Style = ProgressBarStyle.Marquee;
}
private void button1_Click(object sender, EventArgs e)
{
progressBar1.Visible = true;
progressBar1.Enabled = true;
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
System.Threading.Thread.Sleep(10000);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
progressBar1.Visible = progressBar1.Enabled = false;
}
答案 1 :(得分:0)
这就是我开始工作的方式:
我在BackgroundWorker调用之前启用了ProgressBar:
progressBarChanges.Visible = true;
backgroundWorkerShowChanges.RunWorkerAsync();
BackgroundWorker代码从DB获取OracleDataTable:
private void backgroundWorkerShowChanges_DoWork(object sender, System.ComponentModel.DoWorkEventArgs args)
{
holdChanges = GetChangesMade(textBoxID.Text);
}
BackgroundWorker的“已完成”事件更新了用户界面:
private void backgroundWorkerShowChanges_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs args)
{
PopulateChangesGrid();
}
在PopulateChangesGrid()中,在将OracleDataTable对象分配给DGV之后,我将进度条设置为不可见:
private void PopulateChangesGrid()
{
dgvPlatypi.DataSource = holdChanges;
progressBarChanges.Visible = false;
}
它就像一个魅力(< - 不一定是对Windows 8“Metro”魅力的引用)。