キュアジャン開発記録-非同期処理がうまく実装できない件-【解決済】
キュアジャンの事を書き始めて2記事目ですが、早くもコーディングで行き詰りました…読者の皆さん、知恵をお貸しください…
やりたいこと:オンラインアップデート機能の実現
ゲーム起動時にサーバに接続し、最新バージョンがリリースされていれば最新バージョンの実行ファイル(および付随して必要となる設定ファイルやdll等)をダウンロードしてきてローカルのファイルを上書きし、ゲームを起動する。
この機能さえ実現しておけば、最初のリリース時点では盛り込めなかった機能も、後から追加でリリースしていく事が可能です。だから、他の機能は後回しでもいいから、このオンラインアップデート機能だけはなんとしても実装しておきたいのです。
※正確には、オンラインアップデータとゲームアプリケーション本体を別exeファイルに分割し、下記のような流れで実現する予定です。
- ユーザーがオンラインアップデータを起動
- オンラインアップデータは最新バージョンの有無をサーバに問合せする
- 最新バージョンが存在した場合、ダウンロードする
- オンラインアップデータはゲームアプリケーション本体を起動して、自身は終了する。
※ こういう構成にしたため、オンラインアップデート機能以外は最悪、バグっていてもアップデートで後から修正可能なのですが、オンラインアップデート機能自体はバージョンアップできないので、この機能だけは着実に堅牢に構築してリリースしておかないといけないという事になります。
試したこと
CodeZineで「VB.NETによるオンラインアップデート」というそのものズバリな記事を見つけたのでこちらのサンプルコードを参考に、自分のアプリに組み込みました。
codezine.jpテストすると、ちゃんとオンラインアップデート機能が実現できていたのですが、その後で1つ問題点が浮上しました。
上記記事は会員登録が必要なので、簡単にサンプルコードの内容を説明しておくと、サーバにアクセスしてアップデートの有無の確認や、最新バージョンファイルのダウンロードをする間にUIスレッドが応答不能になるのを防ぐために「Forms.Application.DoEvents」を使っていました。しかし、調べたらDoEvents関数でメインスレッドを中断してWindowメッセージを処理するのは現在では非推奨の方法らしいです。
.NET系のエンジニアにどうしたらいいでしょう?と聞くと「最新の.NET FrameworkならAsync/Awaitが使えるから、それ使ってマルチスレッド処理を実現するのが最近の主流ですし、書くの楽だよ」と複数の方からアドバイスいただけました。
Async および Await を使用した非同期プログラミング (C# および Visual Basic)
そこで、上記のDoEventsを使用するバージョンのコードを、AsyncとAwaitを使った形に書き直したのですが、「最新バージョンがあるかどうかチェックする」確認まではちゃんと非同期的処理が実現できていましたが、「最新バージョンをダウンロードしてくる」処理の実行中にTargetInvocationExceptionが発生してしまいました。
今のソースコードはこんな感じです。(GitHubのページへ飛びます)
1) ダウンロード処理本体のクラス
https://github.com/nulluo/ChiriNulluo.Mahjong/blob/master/OnlineUpdaterTest/DownLoader.vb
2) 1)を非同期的に呼び出ししているFormクラス
最新のソースコードから、オンラインアップデート機能に関するところだけ抜き出したものをReleaseに置きましたので手元の環境で動作確認される方は下記のページから「OnlineUpdaterTest-Ver-0.1.1.25.zip」クリックしてダウンロードしてお使いください。(スタートアッププロジェクトはOnlineUpdaterTestです)
質問内容
.NETで、ファイルのダウンロード処理をAsync/Await使って書く場合、どういう形で書くべきなんでしょうか?有識者の方のご意見お待ちしています。
不足している情報などありましたらコメント欄にお寄せください。