【C#】非同期でファイルとフォルダのサイズを表示する
おはようございます。
今回は検索なんかをやる予定でしたが、ちょっと寄り道して
選択されたファイル、フォルダの総数とデータ容量を非同期で画面に表示してみました。
プログラムは前回のものを流用します。
【C#】TreeView と ListView でエクスプローラーみたいな操作をする
スポンサーリンク
画面の修正
リストビューの下にラベルを設置します。
プログラムの修正
ファイルサイズ取得用の非同期メソッドを追加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | // 非同期処理のキャンセル用変数 privateCancellationTokenSource tokenSource=null; /// <summary> /// ファイル数とファイルサイズを設定します. /// </summary> privatevoidSetFileCountAndSize() { // ファイル数、サイズの設定 try { // 非同期処理中だった場合はキャンセル if(tokenSource!=null) { tokenSource.Cancel(); } using(tokenSource=newCancellationTokenSource()) { SetFileCountAndSizeAsync(tokenSource.Token); } } catch(ObjectDisposedException oe) { Console.WriteLine("非同期処理が中止されました。"); } catch(OperationCanceledException ex) { MessageBox.Show("ファイル情報の取得に失敗しました。","エラー"); return; } finally { tokenSource=null; } } /// <summary> /// ファイル数とファイルサイズを設定します(非同期処理). /// </summary> privateasyncvoidSetFileCountAndSizeAsync(CancellationToken token) { longfileSize=0; intfileCount=0; lbl_fileCountValue.Text=""; lbl_fileSizeValue.Text=""; foreach(ListViewItem item inlistViewTo.Items) { token.ThrowIfCancellationRequested(); // ディレクトリだった場合 FileInfo fi=newFileInfo(item.Name); if(fi.Attributes==FileAttributes.Directory) { string[]pathList=Directory.GetDirectories(item.Name,"*",SearchOption.AllDirectories); foreach(stringpath inpathList) { List<long>data=awaitGetFileCountAndSizeTask(path,fileSize,fileCount); lbl_fileSizeValue.Text=getFileSize(data[0]); lbl_fileCountValue.Text=data[1].ToString(); fileSize=data[0]; fileCount=(int)data[1]; } } else { fileSize+=fi.Length; fileCount++; lbl_fileSizeValue.Text=getFileSize(fileSize); lbl_fileCountValue.Text=fileCount.ToString(); } } } /// <summary> /// ファイル数とファイルサイズを取得します. /// </summary> /// <param name="filePath"></param> /// <param name="fileSize"></param> /// <param name="fileCount"></param> /// <returns></returns> privateasyncTask<List<long>>GetFileCountAndSizeTask(StringfilePath,longfileSize,intfileCount) { List<long>result=newList<long>(); awaitTask.Run(()=> { DirectoryInfo dirInfo=newDirectoryInfo(filePath); // フォルダ内の全ファイルの合計サイズを計算する foreach(FileInfo fi indirInfo.GetFiles()) { fileSize+=fi.Length; fileCount++; } result.Add(fileSize); result.Add(fileCount); }); returnresult; } |
既存イベント処理の修正
ファイルの追加、削除時にファイルサイズを設定する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /// <summary> /// 追加ボタンクリックイベント. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> privatevoidbtn_add_Click(objectsender,EventArgse) { varselectedItems=listView1.SelectedItems; foreach(ListViewItem item inselectedItems) { // 項目をコピーして名前を再設定 ListViewItem copy=(ListViewItem)item.Clone(); copy.Name=item.Name; // 既にリストに含まれていないパスであれば追加 if(listViewTo.Items.Find(copy.Name,false).Length==0) { listViewTo.Items.Add(copy); } } // ファイル数、サイズの設定 SetFileCountAndSize(); // 列幅を自動調整 listViewTo.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); } /// <summary> /// 削除ボタンクリックイベント. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> privatevoidbtn_del_Click(objectsender,EventArgse) { varselectedItems=listViewTo.SelectedItems; foreach(ListViewItem item inselectedItems) { listViewTo.Items.Remove(item); } // ファイル数、サイズの設定 SetFileCountAndSize(); // 列幅を自動調整 listViewTo.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); } |
起動してみる
スクリーンショットだと分からないですが、ファイル数、データ容量の大きいフォルダなんかを選択した場合に、非同期で表示が更新されます。
まとめ
最初は非同期でない方法で試したのですが、
大きいファイルなんかだと画面が固まってしまうので非同期にしました。
やっぱり画面まわりも色々やれることがあって楽しいですね。
次回はボタンに画像を表示してみたいと思います。
ディスカッション
コメント一覧
まだ、コメントがありません