2019/10/6追記
書き直しました。
qiita.com
きっかけ
作成中のプログラムでファイルのコピー待ちの時間が気になったので、非同期でやってみました。
IOがボトルネックなプログラムで並列処理やって意味有るのかって言うと無いです。強いて言うならパパっと結果が出て、重い処理は裏でやっておいて貰えるので嬉しいです。(でも結局Copy結果を見る必要は有るんだよな)
参考記事
ぜんっぜん理解できてないです。丸パクリでとりあえず動きました。何書いてあるか理解できるように勉強します。。。
qiita.com
webbibouroku.com
非同期の戻り値の型 (C# および Visual Basic) | Microsoft Docs
ソースコード
プロジェクト全体はGitHubにあげています。
github.com
コピー関数本体
サンプルプロジェクトではoriginalフォルダの中身をcopyフォルダにコピーしています。
'複数タスクでファイルをコピーするプログラム Private Async Function CopyFiles(ByVal files As String()) As Task(Of Boolean) 'タスクをString()の長さ分だけ作成(ラムダ式) Dim tasks As IEnumerable(Of Task(Of Boolean)) = files.Select(Function(file) ( Task.Run(Function() 'Exceptionを拾ったら失敗としてFalseを格納する Try 'テスト用なので強制上書きを有効に、copy\にコピーしている IO.File.Copy(file, "copy\" + IO.Path.GetFileName(file), True) Catch ex As Exception MsgBox(ex.Message) Return False End Try Return True End Function) )) Dim result As IEnumerable(Of Boolean) = Await Task.WhenAll(tasks) '結果待ち '失敗チェック、失敗が有ればFalseを返す For Each flag As Boolean In result If flag = False Then Return False End If Next Return True End Function
使い方
当然ですが、結果を得るためにはWaitする必要が有ります。もし結果を得るなら、待つためにAsyncを関数の前につけてやる必要が有ります。
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click '実行ファイル以下のoriginalという名前のディレクトリに含まれるファイル一覧を取得 Dim files As String() = IO.Directory.GetFiles("original\", "*", IO.SearchOption.TopDirectoryOnly) '取得したファイル一覧に対してコピー開始 Dim task As Task(Of Boolean) = CopyFiles(files) 'Dim task As Task(Of Boolean) = DeleteFiles(files) '何回も押されたくないので無効化 Button1.Enabled = False MsgBox("処理開始") '処理待ち Dim result As Boolean = Await task Button1.Enabled = True MsgBox(result) End Sub
おまけ
丸コピの削除関数です。
'おまけ、ファイル削除 Private Async Function DeleteFiles(ByVal files As String()) As Task(Of Boolean) 'タスクをString()の長さ分だけ作成(ラムダ式) Dim tasks As IEnumerable(Of Task(Of Boolean)) = files.Select(Function(file) ( Task.Run(Function() 'Exceptionを拾ったら失敗としてFalseを格納する Try IO.File.Delete("copy\" + IO.Path.GetFileName(file)) Catch ex As Exception MsgBox(ex.Message) Return False End Try Return True End Function) )) Dim result As IEnumerable(Of Boolean) = Await Task.WhenAll(tasks) '結果待ち '失敗チェック、失敗が有ればFalseを返す For Each flag As Boolean In result If flag = False Then Return False End If Next Return True End Function