在另一个线程中运行进度条

时间:2013-03-07 09:06:20

标签: c#

我正在尝试在单击按钮时显示进度条,并在工作完成时隐藏它。但是当我在按钮事件处理程序中显示进度条时,它不起作用,仅在完成工作后显示。

这是我的代码:

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;
    }
}

3 个答案:

答案 0 :(得分:1)

这是因为您的UI线程正在完成所有工作(访问数据库),直到完成,它无法再处理任何消息(如显示进度条)。

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

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

以下是您的工作:

private void Button_Click_1(object sender,RoutedEventArgs e)

  1. 显示进度条
  2. 使用任务开始后台处理
  3. 向第一个任务添加继续任务,以将消息发送到流程已完成的UI
  4. 在延续任务中使用this.Dispatcher.BeginInvoke,以便UI工作人员在UI线程上发生。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分: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();
}