fork download
  1. using System;
  2. using System.Threading;
  3. using System.Threading.Tasks;
  4. using System.Windows.Forms;
  5.  
  6. namespace DirectoryTask
  7. {
  8. public partial class MainForm : Form
  9. {
  10. IDirectoryTask task = null;
  11. CancellationTokenSource tokenSource = new CancellationTokenSource();
  12.  
  13. public MainForm()
  14. {
  15. InitializeComponent();
  16.  
  17. task = new DirectoryTaskImpl(() => tokenSource, val => tokenSource = val);
  18.  
  19. task.FileProgress += new EventHandler<ProgressEventArgs>(fileProgress);
  20. task.FolderProgress += new EventHandler<ProgressEventArgs>(folderProgress);
  21. task.ExceptionThrown += new EventHandler<ExceptionEventArgs>(exceptionThrown);
  22. task.Complete += new EventHandler<ExitEventArgs>(complete);
  23. }
  24.  
  25. private void Entry(string[] path)
  26. {
  27. if (path != null)
  28. {
  29. foreach (var p in path)
  30. {
  31. if (task.Entry(p, tokenSource.Token) == null)
  32. {
  33. errorListBox.Items.Add("停止処理中のため失敗しました");
  34. }
  35. }
  36. }
  37. }
  38.  
  39. private void Cancel()
  40. {
  41. tokenSource.Cancel();
  42. }
  43.  
  44. #region 進捗の表示、キャンセルイベント
  45.  
  46. private void Progress(ProgressBar bar, decimal progress)
  47. {
  48. bar.Visible = true;
  49. bar.Value = decimal.ToInt32(progress);
  50. }
  51.  
  52. private void complete(object sender, ExitEventArgs e)
  53. {
  54. this.Invoke(new Action(() =>
  55. {
  56. this.fileProgressBar.Visible = false;
  57. this.folderProgressBar.Visible = false;
  58. }));
  59. }
  60.  
  61. private void exceptionThrown(object sender, ExceptionEventArgs e)
  62. {
  63. this.Invoke(new Action(()
  64. => this.errorListBox.Items.Add(e.Exception.Message)
  65. ));
  66. }
  67.  
  68. private void folderProgress(object sender, ProgressEventArgs e)
  69. {
  70. this.Invoke(new Action(() =>
  71. {
  72. this.Progress(this.folderProgressBar, e.Progress);
  73. folderDoneLabel.Text = e.Done.ToString();
  74. folderTotalLabel.Text = e.Total.ToString();
  75. }));
  76. }
  77.  
  78. private void fileProgress(object sender, ProgressEventArgs e)
  79. {
  80. this.Invoke(new Action(() =>
  81. {
  82. this.Progress(this.fileProgressBar, e.Progress);
  83. fileDoneLabel.Text = e.Done.ToString();
  84. fileTotalLabel.Text = e.Total.ToString();
  85. }
  86. ));
  87. }
  88.  
  89. private void cancelButton_Click(object sender, EventArgs e)
  90. {
  91. this.Cancel();
  92. }
  93.  
  94. private void clearErrorButton_Click(object sender, EventArgs e)
  95. {
  96. this.Invoke(new Action(()
  97. => this.errorListBox.Items.Clear()
  98. ));
  99. }
  100.  
  101. #endregion
  102.  
  103. #region ドラッグ・ドロップ
  104.  
  105. protected override void OnDragEnter(DragEventArgs drgevent)
  106. {
  107. if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))
  108. {
  109. drgevent.Effect = DragDropEffects.Copy;
  110. }
  111. base.OnDragEnter(drgevent);
  112. }
  113.  
  114. protected override void OnDragDrop(DragEventArgs drgevent)
  115. {
  116. if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))
  117. {
  118. // ドラッグ中のファイルやディレクトリの取得、処理へのエントリ
  119. this.Entry(drgevent.Data.GetData(DataFormats.FileDrop) as string[]);
  120. }
  121. base.OnDragDrop(drgevent);
  122. }
  123.  
  124. #endregion
  125. }
  126.  
  127. /// <summary>指定されたファイルパスに対して、<see cref="Task"/> 上で非同期かつ再帰的に処理するインターフェースを定義します。</summary>
  128. public interface IDirectoryTask
  129. {
  130. /// <summary>指定されたパスに対して、<see cref="Task"/> 上で非同期かつ再帰的に処理します。</summary>
  131. /// <param name="path">処理対象のパス。</param>
  132. /// <param name="token"><see cref="CancellationToken"/>。</param>
  133. /// <returns>指定されたパスの処理を実行している <see cref="Task"/>。</returns>
  134. Task Entry(string path, CancellationToken token);
  135.  
  136. event EventHandler<ExitEventArgs> Complete;
  137. event EventHandler<ExceptionEventArgs> ExceptionThrown;
  138. event EventHandler<ProgressEventArgs> FileProgress;
  139. event EventHandler<ProgressEventArgs> FolderProgress;
  140. }
  141.  
  142. /// <summary>処理が終了した要因を指定します。</summary>
  143. public enum ExitReason
  144. {
  145. /// <summary>すべての処理対象を処理しました。</summary>
  146. Complete = 0,
  147. /// <summary>処理に失敗しました。</summary>
  148. Fatal = 1,
  149. /// <summary>処理が中断されました。</summary>
  150. Cancel = 2,
  151. }
  152.  
  153. /// <summary>処理が終了したことを示すイベント引数を定義します。</summary>
  154. public class ExitEventArgs : EventArgs
  155. {
  156. /// <summary>終了状態を取得・設定します。</summary>
  157. public ExitReason Reason { get; set; }
  158. }
  159.  
  160. /// <summary>処理の進捗が変化したことを示すイベント引数を定義します。</summary>
  161. public class ProgressEventArgs : EventArgs
  162. {
  163. /// <summary>現在の進捗をパーセンテージ(0~100)で取得します。</summary>
  164. public decimal Progress { get { return Total == 0 ? 0M : 100M * Done / Total; } }
  165. /// <summary>終了した件数を取得・設定します。</summary>
  166. public int Done { get; set; }
  167. /// <summary>処理する全体の件数を取得・設定します。</summary>
  168. public int Total { get; set; }
  169. }
  170.  
  171. /// <summary>処理中に発生した例外のイベント引数を定義します。</summary>
  172. public class ExceptionEventArgs : EventArgs
  173. {
  174. /// <summary>発生した例外を取得・設定します。</summary>
  175. public Exception Exception { get; set; }
  176. }
  177. }
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty