2

在 Windows 窗体中,我有一个搜索框,它触发一个事件来搜索远程数据库并显示一些结果。查询非常快,通常只有几分之一秒,但如果延迟很明显,表单的状态栏中会有一个进度条和标签。当用户点击“搜索”时,状态标签应该会出现,并且进度条会显示一些进度。然后当结果回来时,标签应该消失并且进度条应该是完整的。很基本的回应。

问题是,我不能让这些动作按那个顺序发生。使用下面的代码,我单击“搜索”,直到显示结果之前什么都没有发生,然后进度条从 0 填充到 100。标签永远不会出现。我什至在事件发生后立即输入了一个睡眠命令,以确保我不仅错过了它,而且好像前两条语句没有被执行。我在这里做错了什么?

 private void searchButton_Click(object sender, EventArgs e)
    {
        toolStripStatusLabel1.Visible = true;
        toolStripProgressBar1.Value = 20;
        m_changeRequestedEvents.Fire<String>("SearchTerm", searchTextBox.Text);
        toolStripProgressBar1.Value = 100;
        toolStripStatusLabel1.Visible = false;
    }
4

1 回答 1

2

提供的代码更改了 UI 属性,但在 searchButton_Click 返回之前,线程无法重新绘制 UI。因此,在事件之前所做的更改永远不会应用,因为它们会被之后所做的更改覆盖,然后在方法返回时应用这些更改。

相反,在触发事件之前更新 UI 属性:

searchButton.Enabled = false;
toolStripProgressBar1.Value = 0;
toolStripStatusLabel1.Visible = true;
m_changeRequestedEvents.Fire<String>("SearchTerm", searchTextBox.Text);

并从事件处理程序中,在单独的线程 (BackgroundWorker) 中运行查询,以便 UI 可以同时更新:

private void View_OnSearchTermChangeRequest(Object sender, PropertyChangeRequestEventArgs<String> args)
{
    m_search_bgw = new BackgroundWorker();
    ...
    m_DBHandler.current_worker = m_search_bgw;
    m_search_bgw.RunWorkerAsync(args.RequestedValue);
}

然后在 BackgroundWorker 线程完成时调用的方法中再次更新 UI:

void UpdateView(DataView projects)
{
    dataGridView1.DataSource = projects;
    ...
    toolStripProgressBar1.Value = 100;
    toolStripStatusLabel1.Visible = false;
}
于 2010-10-16T22:38:08.123 回答