Progress という名前のフォームを作って、
プログレスバー(progressBar1) と キャンセルボタン(button1)を貼り付ける。
コードは以下のように。
処理するのは文字列返す関数としている。
Progress.cs
// SetTitle() / SetFunction() で処理設定して ShowDialog()で実行
// 処理関数の中で p.Report(100); したら処理完了と判断する
// その後 GetResult() でタスクで処理した結果の文字列受け取る
// キャンセル時には"キャンセル"が帰る
public partial class Progress : Form
{
CancellationTokenSource cancelTokensource; // キャンセル判定用
string m_result; // 返り値
// 初期化
public Progress()
{
InitializeComponent();
}
// ウインドウタイトル設定
public void SetTitle(string aTitle)
{
this.Text = aTitle;
}
// 処理関数設定
public delegate string Func(IProgress<int> p, CancellationToken cancelToken); // デリゲート宣言
Func m_Func;
public void SetFunction(Func aFunc)
{
m_Func = aFunc;
}
// 処理開始イベント
Task<string> m_Task;
private void Progress_Shown(object sender, EventArgs e)
{
cancelTokensource = new CancellationTokenSource();
var cToken = cancelTokensource.Token;
var p = new Progress<int>(ShowProgress);
m_Task = Task.Run(() => m_Func(p, cToken));
}
// キャンセルボタンクリック
private void button1_Click(object sender, EventArgs e)
{
this.button1.Enabled = false; // もう一回は押せなくする
if (cancelTokensource != null)
{
m_result = "キャンセル";
cancelTokensource.Cancel();//キャンセルを発行
m_Task.Wait();
this.Close();
}
}
//表示更新用
private void ShowProgress(int percent)
{
this.progressBar1.Value = percent;
// 100%で終了と判断する
if( percent == 100 )
{
m_Task.Wait();
m_result = m_Task.Result;
this.Close();
}
}
// 返り値取得
public string GetResult()
{
return m_result;
}
}
こっちはProgressを使って重い処理を実行する呼び出し側
string 重い処理(IProgress<int> p, CancellationToken cancelToken){
// 重い処理する
//...
return "返り値";
}
private void button1_Click(object sender, EventArgs e)
Progress progress = new Progress();
progress.SetTitle("重い処理中");
progress.SetFunction(重い処理);
progress.ShowDialog();
string result = progress.GetResult();
if (result == "キャンセル")
{
MessageBox.Show("キャンセルしました。");
}
}