1 // OpenTween - Client of Twitter
2 // Copyright (c) 2015 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
17 // You should have received a copy of the GNU General public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
23 using System.Collections.Generic;
24 using System.ComponentModel;
27 using System.Threading;
28 using System.Threading.Tasks;
29 using System.Windows.Forms;
34 /// タスクが待機中であることを表示するダイアログ
37 /// 一定時間 (Timeout プロパティで指定する) 以上経ってもタスクが完了しない場合にダイアログを表示します。
38 /// EnableCancellation メソッドを使用することでキャンセル機能を提供することも可能です。
40 public partial class WaitingDialog : OTBaseForm
42 private readonly Lazy<CancellationTokenSource> cancellationTokenSource;
44 private bool cancellationEnabled = false;
47 /// ダイアログを表示せずに待機する最短の待ち時間 (デフォルト0.5秒)
49 public TimeSpan Timeout { get; set; }
56 get { return this.labelMessage.Text; }
57 set { this.labelMessage.Text = value; }
60 public WaitingDialog()
62 this.InitializeComponent();
64 this.cancellationTokenSource = new Lazy<CancellationTokenSource>();
66 this.Timeout = TimeSpan.FromMilliseconds(500);
69 public WaitingDialog(string message)
72 this.Message = message;
76 /// キャンセル機能を有効にし、キャンセルを通知するための CancellationToken を返します
78 public CancellationToken EnableCancellation()
80 this.cancellationEnabled = true;
81 this.ControlBox = true;
83 var cts = this.cancellationTokenSource.Value;
87 public Task WaitForAsync(Task task)
89 return this.WaitForAsync(this.ConvertTaskWithValue(task));
92 public Task WaitForAsync(IWin32Window owner, Task task)
94 return this.WaitForAsync(owner, this.ConvertTaskWithValue(task));
97 public Task<T> WaitForAsync<T>(Task<T> task)
99 return this.WaitForAsync(null, task);
103 /// タスクを待機し、状況に応じて待機中ダイアログを表示します
105 /// <param name="owner">ダイアログのオーナー</param>
106 /// <param name="task">待機するタスク</param>
107 public Task<T> WaitForAsync<T>(IWin32Window owner, Task<T> task)
109 return Task.Run(async () =>
111 // 指定された秒数以内で完了すればダイアログは表示しない
112 var timeout = Task.Delay(this.Timeout);
113 if (await Task.WhenAny(task, timeout) != timeout)
116 var dialogTask = this.InvokeAsync(() => this.ShowDialog(owner));
118 // キャンセルされずにタスクが先に完了したらダイアログを閉じる
119 if (await Task.WhenAny(task, dialogTask) != dialogTask)
120 await this.InvokeAsync(() => this.DialogResult = DialogResult.OK);
126 /// <summary>Task を Task<T> に変換したいだけ</summary>
127 private async Task<int> ConvertTaskWithValue(Task task)
129 await task.ConfigureAwait(false);
133 private void ProgressDialog_FormClosing(object sender, FormClosingEventArgs e)
135 if (this.cancellationEnabled)
137 if (e.CloseReason == CloseReason.UserClosing)
139 var cts = this.cancellationTokenSource.Value;
145 private void ProgressDialog_KeyDown(object sender, KeyEventArgs e)
147 if (this.cancellationEnabled)
149 if (e.KeyCode == Keys.Escape)
151 var cts = this.cancellationTokenSource.Value;
154 this.DialogResult = DialogResult.Cancel;