WPFアプリケーションの無期限の進行状況バーは表示されませんが、プロセスはバックグラウンドで実行されています

user9610829

プロセスを機能させると、ProgressBarを追加してプロセスがクラッシュしていないことをユーザーに知らせるために、スレッドの問題が発生した可能性があります。これで十分なので、IndefiniteProgressBarは私にとっては問題ありません。

 <ProgressBar x:Name="ProcessProgress" Minimum="0" Maximum="100" Visibility="Hidden" IsIndeterminate="False" Width="305" Height="20" Margin="240,214,248,10"></ProgressBar>

スタートボタンがクリックされる前に表示されない長さの決定的なプログレスバーを開始しようとしました:

private void Start_Click(object sender, RoutedEventArgs e)
{
    ...
    //process starts here
    var fP = new FileProcessor();
    ProcessProgress.IsIndeterminate = true;
    ProcessProgress.Visibility = Visibility.Visible;

    ...
    //finally show the progressbar as full when done
    ProcessProgress.IsIndeterminate = false;
    ProcessProgress.Value = ProcessProgress.Maximum;

}

プロセス全体を実行するだけで、バーが表示されません。

プロセス中にプログレスバーを生成するにはどうすればよいですか?

パナギオティスカナボス

問題は、すべてのコードがUIスレッドで実行されることです。UIは、プロセス全体が終了する前に自分自身を更新する機会がありません。

Task.Run()UIをブロックせずに、バックグラウンドで重いジョブを実行するために使用できますawaitキーワードを使用して、UIをブロックせずにそのタスクが完了するのを待つことができますタスクが完了すると、UIスレッドに戻り、UIを再度変更できます。

このイベントハンドラーの迅速で汚い修正は次のようになります。

private async void Start_Click(object sender, RoutedEventArgs e)
{
    ProcessProgress.IsIndeterminate = true;
    ProcessProgress.Visibility = Visibility.Visible;
      ...
    await Task.Run(()=>
    {
        //process starts here
        var fP = new FileProcessor();

        ...
    });

    //We are back in the UI thread, we can modify the UI
    ProcessProgress.IsIndeterminate = false;
    ProcessProgress.Value = ProcessProgress.Maximum;
}

InvokeUIスレッドに戻るために使用する必要はありませんawait。それ自体が仕事です

についてのメモasync voidこれは、イベントハンドラーまたは同様のメソッドのみを対象としています。メソッドを待つことはできませんasync void。つまり、何か問題が発生した場合でも例外を取得することはできません。何も返さない非同期メソッドには、async Task署名が必要です。

進行状況を報告する場合は、ここで説明するように、IProgressインターフェイスとProgressクラスを使用できますProgressクラスは、コールバックを呼び出すか、作成されたスレッドでイベントを発生させます。ペイロードは、パーセンテージだけでなく、任意のクラスにすることができます

ボタンハンドラーをクリーンに保つために、レポートコードを別のメソッドに移動することをお勧めします。コードは次のようになります。

//The progress class
class FileProgress
{
    public string FileName{get;set;}
    public int Progress{get;set;}
    public string Message{get;set;}

    public FileProgress(string fileName,int progress,string message)
    {
        FileName=filename;
        Progress=progress;
        Message=message;
    }
}

//In the form itself
private void ReportStart()
{
    ProcessProgress.IsIndeterminate = true;
    ProcessProgress.Visibility = Visibility.Visible;
}

private void ReportEnd()
{
    ProcessProgress.IsIndeterminate = false;
    ProcessProgress.Value = ProcessProgress.Maximum;
}

private void ReportProgress(FileProgress progress)
{
    ProcessProgress.Value =progress.Progress;        
    PanelStatus.Text = $"Working on {progress.FileName} : {progress.Message}";
}

イベントハンドラは次のようになります。

private async void Start_Click(object sender, RoutedEventArgs e)
{
    ReportStart();

    IProgress<FileProgress> progress=new Progress<FileProgress>(ReportProgress);
      ...
    await Task.Run(()=>
    {
        //process starts here
        var fP = new FileProcessor();

        foreach(var file in someFiles)
        {
              progress.Report(new FileProgress(file,0,"Starting");
              //Do some processing
              progress.Report(new FileProgress(file,100,"Finished");
        }
        ...
    });

    //We are back in the UI thread, we can modify the UI
    ReportEnd();
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ