Hatena::Groupmediaforcelabs

御手洗の開発記録

2010-06-17

Silverlight対応WCFサービスの同期実行について

| 18:27

こんにちは。

Silverlightからバッグ側の処理を実行するために、Silverlight対応WCFサービスを利用しています。

何も考えず実装すると非同期実行になってしまいますが、どうしても同期実行がしたいのでいろいろ調べてみました。

結論から言うと、Silverlight対応WCFサービスでは同期実行が出来ませんでした。

自分は以下の2つの方法を試してみました。


1.AutoResetEventを使って非同期実行の終了を待つ方法

AutoResetEventやManualResetEventを利用して別スレッドで起動している(はず)終了処理の完了を待機する方法を試してみました。

ソースは以下の通りです。

namespace SilverlightWCFTest
{
    public partial class MainPage : UserControl
    {
        private AutoResetEvent are = new AutoResetEvent(false);

        public MainPage()
        {
            InitializeComponent();

            // サービスを非同期で実行する
            var proxy = new EchoServiceClient();
            proxy.GetMessageCompleted += new EventHandler<GetMessageCompletedEventArgs>(proxy_GetMessageCompleted);
            proxy.GetMessageAsync();

            // proxy_GetMessageCompletedメソッド終了まで待機する
            are.WaitOne();
        }

        void proxy_GetMessageCompleted(object sender, GetMessageCompletedEventArgs e)
        {
            // 画面に結果内容を反映する
            MainPageContext context = (MainPageContext)Resources["Context"];
            context.Message = e.Result;

            // 完了を通知する
            are.Set();
        }
    }
}

この方法でやると、なぜかproxy_GetMessageCompletedが実行されません。

スレッドIDを確認すると、別のスレッドになっているようですが、なぜかWaitOne()で止まったままになってしまいます。


2.チャネルモデルでWCFを実行する方法

IAsyncResultにAsyncWaitHandleというプロパティがあったので、そのオブジェクトを使用して同期する方法を試してみました。

ソースは以下の通りです。

namespace SilverlightWCFTest
{
    public partial class MainPage : UserControl
    {
        SynchronizationContext uiThread;

        public MainPage()
        {
            InitializeComponent();

            uiThread = SynchronizationContext.Current;

            // チャネルモデルのサービスを生成して実行する
            var channel = new EchoServiceClient().ChannelFactory.CreateChannel();
            IAsyncResult asyncResult = channel.BeginGetMessage(GetMessageCallback, channel);

            // サービス完了まで待機する
            ((ManualResetEvent)asyncResult.AsyncWaitHandle).WaitOne();
        }

        private void GetMessageCallback(IAsyncResult asyncResult)
        {
            string message = ((EchoService)asyncResult.AsyncState).EndGetMessage(asyncResult);

            // 画面を更新する
            uiThread.Post(UpdateUI, message);

            // 処理の終了を通知する
            ((ManualResetEvent)asyncResult.AsyncWaitHandle).Set();
        }

        private void UpdateUI(object obj)
        {
            MainPageContext context = (MainPageContext)Resources["Context"];
            context.Message = (string)obj;
        }
    }
}

このやり方でもGetMessageCallback()メソッドが実行されず、WaitOne()で止まったままになってしまいます。

その他にもいろいろ調査してみましたが、結局同期実行はできませんでした。

一番不可解なのは、1のやり方で同期実行ができなかったことです。

この方法はWCFというよりも.NET FrameworkAPIを使っているはずなのですが、別スレッドになっているはずの処理が実行されませんでした。

自分の勉強不足で根本的に何か間違えているのかもしれませんが、ちょっと納得がいかないです。

今後、時間のあるときに再度調査していきたいと思います。

それでは、また。

CristinitaCristinita2012/02/20 14:02Now that's stuble! Great to hear from you.

hmrnetspqzzhmrnetspqzz2012/02/21 18:19ysqMY3 <a href="http://pfdwclitxnhy.com/">pfdwclitxnhy</a>

wiqvtymmrwiqvtymmr2012/02/21 22:20DmQpO9 , [url=http://ozqvrzwpumgd.com/]ozqvrzwpumgd[/url], [link=http://pfanabyotmfu.com/]pfanabyotmfu[/link], http://enlbfxbqqkol.com/

yzehriftghyzehriftgh2012/02/29 02:25B00Kkc <a href="http://vsykehbryolr.com/">vsykehbryolr</a>