次に、非同期メソッドの完了をイベント・ハンドラで処理するコードを示す(実行結果は同じである)。
static void Main(string[] args)
{
IAsyncOperation<DeviceInformationCollection> deviceInfo;
deviceInfo = DeviceInformation.FindAllAsync(); // …… (1)
deviceInfo.Completed += FindAllAsyncCompleted; // …… (2)
while (deviceInfo.Status != AsyncStatus.Completed) // …… (3)
{
System.Threading.Thread.Sleep(500);
}
Console.WriteLine("Dummy"); // …… (4)
Console.ReadKey();
}
static void FindAllAsyncCompleted(IAsyncOperation<DeviceInformationCollection> asyncInfo, AsyncStatus asyncStatus) // …… (5)
{
DeviceInformationCollection deviceCollection;
deviceCollection = asyncInfo.GetResults(); // …… (6)
foreach (DeviceInformation device in deviceCollection) // …… (7)
{
Console.WriteLine("Name={0}, ID={1}", device.Name, device.Id);
}
}
Sub Main()
Dim deviceInfo As IAsyncOperation(Of DeviceInformationCollection)
deviceInfo = DeviceInformation.FindAllAsync() ' …… (1)
deviceInfo.Completed = AddressOf FindAllAsyncCompleted ' …… (2)
While (deviceInfo.Status <> AsyncStatus.Completed) ' …… (3)
System.Threading.Thread.Sleep(500)
End While
Console.WriteLine("Dummy") ' …… (4)
While (True)
Dim l = Console.ReadLine()
If l = "q" Then
Exit While
End If
System.Threading.Thread.Sleep(500)
End While
End Sub
Sub FindAllAsyncCompleted(asyncInfo As IAsyncOperation(Of DeviceInformationCollection), asyncStatus As AsyncStatus) ' …… (5)
Dim deviceCollection As DeviceInformationCollection
deviceCollection = asyncInfo.GetResults() ' …… (6)
For Each device As DeviceInformation In deviceCollection ' …… (7)
Console.WriteLine("Name={0},ID={1}", device.Name, device.Id)
Next
End Sub
この方法のようにIAsyncOperationオブジェクトのCompletedイベントを処理するようにしても、非同期処理を同期的に扱うために余計なコード(具体的にはループによる待機)が必要になる点は同じだが、非同期メソッドの結果を取得するロジックやコードをイベント・ハンドラ内に集約できるメリットが生まれている。しかし、このコードには問題が多い。詳しくは説明しないが、これはイベントが何のスレッドで呼び出されているかという問題であり、この問題はGUIを使用するアプリでは問題となる可能性が高いのだ*7。だからこそ、次の応用編で非同期編を説明したい。
*7 この理由からサンプル・コードは、コンソール・アプリとして記述している。
リスト4では、非同期メソッドを同期的に扱うためのマジック・コードが2箇所に存在している。特に問題なのが、完了時のイベント・ハンドラを待ち受けるためのマジック・コードである。筆者の環境では、C#版のコードはConsole.WriteLineメソッドを挟むことで正常に動作する。しかし、VB版のコードは結果を出力する前にMain関数が終了してしまうために、終了キー(=[q]キー)を押すまで待つように作成しなければならなかった。きっと、試す環境によっては、異なる結果が出るはずである。これが、非同期メソッドを簡易的な同期コードに書き起こすことの弊害である。本来であれば、もっと慎重にコードを設計すべきなのだ。ただし、本稿はデスクトップ・アプリからのWinRTの使い方を説明することを目的にしており、実用的なコードを提供することにはない。あくまでも、動作確認を目的とするコードであることを念頭に置いて読んでほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.