1

我试图在单击按钮时显示进度条,并在工作完成时将其隐藏。但是当我在按钮事件处理程序中显示进度条时,它不起作用,只有在工作完成后才会显示。

这是我的代码:

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    this.Dispatcher.BeginInvoke((Action)(() =>
        {
            loadingprgoress.Visibility = Visibility.Visible;
        }));

    int usresult, psresult;

    con.Open();

    SqlDataReader data = null;
    String myQueryEdit1 = @"SELECT Username, Password FROM [dbo].[Table]";
    com.CommandText = myQueryEdit1;
    com.Connection = con;
    data = com.ExecuteReader();
    Random rnd = new Random();
    int newrnd = rnd.Next(1, 100);

    if (data.Read())
    {

        string userhash = GenerateHashWithSalt(data["Username"].ToString(), newrnd.ToString());
        string passhash = GenerateHashWithSalt(data["Password"].ToString(), newrnd.ToString());
        string userhash1 = GenerateHashWithSalt("admin", newrnd.ToString());
        string passhash1 = GenerateHashWithSalt(pasbox.Password, newrnd.ToString());

        usresult = userhash.CompareTo(userhash1);
        psresult = passhash.ToString().CompareTo(passhash1);
        if (usresult == 0 && psresult == 0)
        {
            con.Close();
            dental_main_Window neww = new dental_main_Window();
            neww.Show();
            Close();
        }
        else
        {
            con.Close();
            pasbox.Password = "";
        }

        Thread.Sleep(3000);

        this.Dispatcher.BeginInvoke((Action)(() =>
           {
               loadingprgoress.Visibility = Visibility.Hidden;
           }));
        return;
    }
}
4

3 回答 3

1

发生这种情况是因为您的 UI 线程正在完成所有工作(访问数据库),并且在完成之前,它无法处理更多消息(例如显示进度条)。

您需要做相反的事情,在没有 BeginInvoke 的 UI 线程中显示进度条,并在另一个线程中进行数据库访问。当您其他线程完成时,您需要在 UI 线程上执行 BeginInvoke 以隐藏进度条。

这是另一个重要的注意事项:this.Dispatcher.BeginInvoke 不会产生线程。它将命令“推送”到 UI 线程的队列,因为所有 UI 操作都必须从 UI 线程执行。

这是你要做的:

私人无效Button_Click_1(对象发送者,RoutedEventArgs e)

  1. 显示进度条
  2. 使用任务启动您的后台进程
  3. 将延续任务添加到您的第一个任务,以将消息发送到流程已完成的 UI
  4. 在延续任务中使用 this.Dispatcher.BeginInvoke 以便 UI 人员发生在 UI 线程上。
于 2013-03-07T09:15:37.737 回答
0

WPF 中的 UI 需要在 UI 线程上执行。你认识到这一点,因为我可以看到你Dispatcher.BeginInvoke用来与你的进度窗口进行交互。

不过,您的问题是您也在 UI 线程上执行长时间运行的任务。当你这样做时,你不会给进度窗口一个操作的机会。该线程被长时间运行的任务消耗,因此无法为 UI 提供服务。

解决方案是远离 UI 线程执行长时间运行的任务。

于 2013-03-07T09:11:48.563 回答
0

看看后台工作人员(http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

它允许您在单独的专用线程上运行操作。在后台计算期间,您可以引发ProgressChanged事件以通知 UI 并相应地更新 ProgressBar:

private BackgroundWorker _worker;

public Form1(string[] args)
{
    InitializeComponent();


    _worker = new BackgroundWorker();
    _worker.WorkerReportsProgress = true;

    _worker.RunWorkerCompleted += worker_WorkCompleted;
    _worker.DoWork += worker_DoWork;
    _worker.ProgressChanged += worker_ProgressChanged;


}

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    DoStuff();
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}
private void worker_WorkCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    _running = false;
    UpdateUi();
}

private bool DoStuff()
{
        //...
        _worker.ReportProgress(20);
        //...
        _worker.ReportProgress(20);

        return true;

}

private void btnUpdate_Click(object sender, EventArgs e)
{
    _worker.RunWorkerAsync();
}
于 2013-03-07T09:31:56.980 回答