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 を実行して進行状況バーを非表示にする必要があります。

もう 1 つ重要な注意事項があります。 this.Dispatcher.BeginInvoke はスレッドを生成しません。すべての UI 操作は UI スレッドから実行する必要があるため、コマンドを UI スレッドのキューに「プッシュ」します。

これがあなたがすることです:

private void 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

Have a look at background worker (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx)

It allows you to run an operation on a separate, dedicated thread. During the background computation, you can raise the ProgressChanged event to notify the UI and update the ProgressBar accordingly:

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 に答える