2012年12月01日

.NET Framework4.5 での非同期I/O処理 事始め

   このエントリーをはてなブックマークに追加 Clip to Evernote

この記事は、C# Advent Calender 2012 http://atnd.org/events/33905 への参加記事です。
今年もC# Advent Calender が開始されました。

なかなか書くネタが見つからず、参加しようかどうか悩んでいるうちに、気が付いたら、空いている日が、
初日の 12/1 と 最終日の 12/25 の2日だけになってました。さすがに最終日はプレッシャーがかかると
思ったので、初日である 12/1 にエントリーさせてもらいました。

さて、お題は、「.NET Framework4.5 での非同期I/O処理 事始め」です。
既に多くの方がブログで async, awaitの記事を書いているので、2番煎じ、3番煎じの感は
否めませんが、まあ、このC# Advent Calenderは、ゆるいイベントということなので、大目
に見てください(^^;

さて、ここからが本題です。

.NET Framework4.5から、非同期IOをサポートする新しいasync系メソッドが追加されています。
これにより、従来よりもより簡単に非同期IO処理が書けるようになりました。

■.NET Framework4.0 以前の非同期I/O処理


まずは、.NET Framework4.0 以前はどうだったかを振り返ってみましょう。
これまでの Streamクラスには、BeginRead, EndRead といった非同期IOをサポートするメソッドが
用意されていました。
従来の非同期IOの簡単なサンプルを以下に示します。
このコードは、Sample.txtファイルを非同期IOで読み込み、TextBox にその内容を表示しています。

※ 今回は、WindowsFormsを使いましたが、WPFでもなんら変わることはありません。


ファイルのサイズが小さければ、こんな面倒なコードを書かずに、File.ReadAllTextで一気に
読み込んでしまって良いと思いますが、巨大なファイルの場合は、UIがフリーズするのを防止できません。
UIのフリーズを防止するには、スレッドを起動するとか、BackgroundWorkerクラスを利用するとか、Taskを使うとか、
いろいろと方法はありますが、同期処理に比べると面倒です。

それと、上記のコードは、テキストファイルを扱うのに、ReadLine系のメソッドを使えないため、byte配列に
読み込んでいて、いまいち感がぬぐえません。


■.NET Framework4.5 での非同期I/O処理


では、C#5.0 + .NET Framework4.5ではどうなるかを見てみましょう。


上記コードの注目点は、以下の4点です。

1. メソッドに、async キーワードが付いている。
2. ReadLineAsync() という非同期IOメソッドを使っている。
3. この非同期IOメソッドに、await キーワードをつけている。
4. 同期処理のように、UIへのアクセスを普通に行っている。

メソッドに、await キーワードを使う場合には、必ずメソッドにasync キーワードをつける必要があります。
そして、await を使うことで、非同期処理をあたかも同期処理のように書くことが
可能になります。
いやー、これはほんとうに便利ですね。

■IProgressによるロジックとUIの分離


でも、ファイルIO処理の中で、UIにアクセスするコードを書くのは嫌だ! と思う人も多いと思います。
大丈夫です。.NET Framework4.5では、そういった要求にも簡単にこたえることができます。
コードを示します。


ReadTextDataメソッドの引数に、Progress オブジェクトを渡しています。
このProgress のコンストラクタの引数に、コールバックされるラムダ式を記述します。
ここで、UI処理を書くわけですね。
ReadTextData メソッドの中では、progress.Report(s) と、Reportメソッドを呼び出しています。
このタイミングで、先ほどのコールバックが呼び出されることになります。
これで、ReadTextDataメソッドは、完全にUIとは分離されたので、Formクラスに書く必要もなくなりましたね。

Write系のコードも載せようと思ったのですが、まあ、上記とほとんど同じ感覚で書けるので、
あえて載せる必要もないでしょう。



 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52290230