今回は、サービスメソッドの非同期処理について。
WCFでは、「サービス参照の追加」を利用してクライアントプロキシを作成する際に
非同期処理が行えるようにできるオプションがあります。
このオプションを設定して、クライアントプロキシを作成すると
IAsyncResultを利用したおなじみの非同期処理メソッドが作成されます。
オプションは、「サービス参照の追加」ダイアログにて「非同期操作の生成」チェックボックス
をチェックすれば作成されます。
呼び出し方法は、いつものやり方です。
以下、サンプルです。
まず、サービス定義。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace Gsf.Samples.WCF { [ServiceContract] public interface IMyService { [OperationContract] string GetData(int value); } }
using System; using System.Collections.Generic; using System.Linq; namespace Gsf.Samples.WCF { public class MyService : IMyService { public string GetData(int value) { System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2)); return string.Format("you enter: {0}", value); } } }
次にホストアプリ。
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { class Program { static void Main() { using (var host = new ServiceHost(typeof(MyService))) { host.Open(); Console.WriteLine("サービスが開始されました。"); Console.WriteLine("press <ENTER> to exit..."); Console.ReadLine(); host.Close(); } } } }
ホスト側のアプリケーション構成ファイル。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="Gsf.Samples.WCF.MyService"> <host> <baseAddresses> <add baseAddress="http://localhost:8090/WCFSample010/MyService"/> </baseAddresses> </host> <endpoint address="" binding="basicHttpBinding" contract="Gsf.Samples.WCF.IMyService" /> </service> </services> </system.serviceModel> </configuration>
次にクライアントアプリ。
クライアントアプリのボタンをクリックすると内部で
非同期処理が実行されます。コールバックにて、画面のラベルに
結果を表示するようになっています。
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.ServiceModel; using Client.MyServiceRef; namespace Client { public partial class Form1 : Form { private int _count; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { lblResult.ResetText(); ActiveControl = btnCallServiceMethod; _count = 100; } private void btnCallServiceMethod_Click(object sender, EventArgs e) { var client = new MyServiceClient(); client.BeginGetData( _count++ ,GetDataAsyncCallback ,client ); } private void GetDataAsyncCallback(IAsyncResult ar) { MyServiceClient client = (MyServiceClient) ar.AsyncState; Control control = lblResult; Action<string> action = UpdateResult; string result = string.Empty; try { result = client.EndGetData(ar); control.Invoke(action, result); } catch (CommunicationException ex) { control.Invoke(action, ex.Message); client.Abort(); } finally { if (client.State != CommunicationState.Closed) { client.Close(); } } } private void UpdateResult(string result) { lblResult.Text = result; } } }
クライアント側のアプリケーション構成ファイル。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="http://localhost:8090/WCFSample010/MyService" binding="basicHttpBinding" contract="MyServiceRef.IMyService" /> </client> </system.serviceModel> </configuration>
実行すると以下のようになります。実際に動かしてみると
ボタンを押下した後、すぐに制御が戻ってきて、結果が返ってくるまで
UIはブロックされずに動作します。
サンプルは以下の場所にアップしてあります。
https://sites.google.com/site/gsfzero1/Home/WCFSample-010.zip?attredirects=0&d=1
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ