WinFormsアプリケーション内で使用する進行状況/キャンセルフォームを作成して、待機可能な「操作」を実行し、ユーザーに進行状況情報と操作をキャンセルする機会を提供しようとしています。
フォームはを使用して表示されるため、ShowDialog()
下のフォームを適切に無効にするモーダルフォームです。したがって、他のフォームのすべてのコントロールを無効にすることをいじくり回す必要はありません。
彼らは私がそれを実装した方法で、あなたが細断処理することを完全に期待しています:-)、Form.Load
イベントハンドラーの間に操作の結果を待ち、操作が完了したらフォームを閉じます(それが理由であるかどうかにかかわらず)完了するまで実行されたか、キャンセルされたか、例外が発生しました)。
public partial class ProgressForm<T> : Form
{
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private Progress<string> _progress = new Progress<string>();
private Func<IProgress<string>, CancellationToken, Task<T>> _operation = null;
private Exception _exception = null;
private T _result = default(T);
public static T Execute(Func<IProgress<string>, CancellationToken, Task<T>> operation)
{
using (var progressForm = new ProgressForm<T>())
{
progressForm._operation = operation;
progressForm.ShowDialog();
if (progressForm._exception != null)
throw progressForm._exception;
else
return progressForm._result;
}
}
public ProgressForm()
{
InitializeComponent();
this._progress.ProgressChanged += ((o, i) => this.ProgressLabel.Text = i.ToString());
}
private async void ProgressForm_Load(object sender, EventArgs e)
{
try
{
this._result = await this._operation(this._progress, this._cancellationTokenSource.Token);
}
catch (Exception ex) // Includes OperationCancelledException
{
this._exception = ex;
}
this.Close();
}
private void CancelXButton_Click(object sender, EventArgs e)
{
if (this._cancellationTokenSource != null)
this._cancellationTokenSource.Cancel();
}
}
これは次のように呼ばれます:
int numberOfWidgets = ProgressForm<int>.Execute(CountWidgets);
...待機可能なCountWidgets()
ものはどこにありますか(この場合、Task<int>
適切なIProgressとCancellationToken
パラメーターを使用して関数が返されます)。
これまでのところかなりうまく機能していますが、追加したい「機能」が1つあります。理想的には、フォームを(たとえば)1秒間非表示にして、操作が非常に迅速に完了した場合に、フォームが表示されてすぐに再び非表示になる「ちらつき」がないようにします。
だから、私の質問は、フォームが表示される前に1秒の遅延を導入する方法です。もちろん、すぐに操作を開始したいのですが、操作の結果を「待つ」とすぐに、Form.Load
イベントハンドラーの呼び出し元に制御が戻されるため、(いわば)制御できなくなります。 -フォームを表示する作業を続行します。
基本的に2番目のスレッドが本当に必要であり、メインUIスレッドをブロックしている間にそのスレッドで実行する操作が必要だと思います。(UIスレッドをブロックすることは嫌われていることは知っていますが、この場合、実際に必要なものだと思います)。
スレッドなどを作成する方法はたくさんあるので、新しい「非同期/待機」の世界でこれを行う方法がわかりません...