2012-04-30 14 views
1

サーバーとクライアントの両方の使用の.Net 4上の2つの機能を実現するために、非同期Webサービスのコールバック - どのようにサーバ側

、現在は非同期Webサービスの呼び出しを行うためにコールバックを使用しました。

しかし、サーバーが行っている作業には時間がかかり、サーバー(クライアントに似ています)でリクエストスレッドを解放したいと考えています。

.Netコールバックを使用してサーバー上の関数Aを呼び出すことは可能ですか?

関数B(サーバー上)は、クライアントのコールバック関数への応答を返しますか?

私はAsynchronous Web Service Calls over HTTP with the .NET Framework(WCFなし)を使用しています。このサンプルコードで

おかげ

ラファエル

答えて

0

は、クライアントECFサーバーとサーバーで関数を呼び出し、クライアントの機能を呼び出します。

次のサンプルでは、​​イベントサブスクリプションも確認できます。

サンプルコードSampleServiceClient:サーバー側での

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.Text; 
using SampleServiceClient.SampleServiceReference; 
using System.Windows.Forms; 
using System.Threading; 
using System.ComponentModel; 


namespace SampleServiceClient 
{ 
    /*WCF duplex use a SynchronizationContext by default, which means the callback will happen on UI threadm, 
    * so that you can update UI in your callback. But your client are calling your server in on the UI thread, 
    * so the callback will never be able to be delivered to your client. that's the orignal reason why it blocked. 
    * 
     Now if you use Synchronization=false, the callback will be delivered to you by a non-UI thread, 
    * that's why you can receive the callback now. 

    * After you receive the callback, you still want to update the UI in the UI thread, 
    * but the UI thread is still blocking now waiting for server response, so that's why it is blocking again, is it right?*/ 


    [CallbackBehavior(UseSynchronizationContext = false)] 
    class SampleCallback : IService1Callback 
    { 
     frmClient frm; 
     public SampleCallback() 
     { 

     } 
     public SampleCallback(frmClient Form1) 
     { 

      frm = Form1; 
     } 
     public void ShowCallbackMessage(string message) 
     { 
      SetText("Callback message --> " + message); 
     } 

     public void OnPriceChanged(int value) 
     { 
      SetText("On Price Changed by client number : " + value.ToString()); 
     } 

     private void SetText(String str) 
     { 
      SendOrPostCallback instance = new SendOrPostCallback(frm.AddItem); 
      frm.BeginInvoke(instance, str); 
     } 

    } 
} 

コード:

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 
using System.Text; 

namespace SampleService 
{ 
    //No Service Contract Tag for Callback Inteface 
    interface ISampleCallback 
    { 
     [OperationContract(IsOneWay = true)] 
     void ShowCallbackMessage(string message); 

     [OperationContract(IsOneWay = true)] 
     void OnPriceChanged(int value); 

    } 

//Name of Callback Contract on the WCF Service Contract which we want to expose to client 
    //You can assosiate only one CallBack Interface with a WCF Service Contract 
    [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ISampleCallback))] 
    public interface IService1 
    { 
     [OperationContract] 
     string GetData(int value); 

     [OperationContract (IsOneWay=true)] 
     void ChangePrice(int value); 

     //Code to Show Events Programming 
     [OperationContract] 
     bool SubscribeToPriceChangedEvent(); 

     [OperationContract] 
     bool UnsubscribeFromPriceChangedEvent(); 
    } 

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, 
       ConcurrencyMode = ConcurrencyMode.Reentrant)] 
    public class Service1 : IService1 
    { 
     static List<ISampleCallback> clients = new List<ISampleCallback>(); 
     private ISampleCallback callback=null; 
     internal ISampleCallback Callback 
     { 
      get { return callback; } 
      set { callback = value; } 
     } 

     public string GetData(int value) 
     { 
      //Invoke the callback operation in the client operation 
      callback = OperationContext.Current.GetCallbackChannel<ISampleCallback>(); 
      //All WCF channels implements the ICommunicationObject interface. 
      //If State is not opened then the service should not attempt to use callback. 
      if (((ICommunicationObject)callback).State == CommunicationState.Opened) 
      { 

       Callback.ShowCallbackMessage("You are the client number " + value.ToString()); 
      } 
      return string.Format("Callback message sent to client number " + value.ToString()); 
     } 

     public void ChangePrice(int value) 
     { 
      raisePriceChangedEvent(value); 
     } 

     //Event Programming 
     public bool SubscribeToPriceChangedEvent() 
     { 
      try 
      { 
       Callback = OperationContext.Current.GetCallbackChannel<ISampleCallback>(); 
       if (!clients.Contains(Callback)) 
       { 
        clients.Add(Callback); 
       } 
       return true; 
      } 
      catch (Exception) 
      { 
       return false; 
      } 

     } 

     public bool UnsubscribeFromPriceChangedEvent() 
     { 
      try 
      { 
       Callback = OperationContext.Current.GetCallbackChannel<ISampleCallback>(); 
       clients.Remove (Callback); 
       return true; 
      } 
      catch (Exception) 
      { 
       return false; 
      } 
     } 

     private void raisePriceChangedEvent(int value) 
     { 
      clients.ForEach(delegate(ISampleCallback oCallback) 
       { 
        if (((ICommunicationObject)oCallback).State == CommunicationState.Opened) 
        { 
         oCallback.OnPriceChanged(value); 
        } 
        else 
        { 
         clients.Remove(oCallback); 
        } 

       }); 
     } 
    } 
} 
+0

おかげで、しかし、それは、WCFなしで可能ですか? HTTPフレームワークで非同期Webサービス呼び出しを使用しています。http://msdn.microsoft.com/en-us/library/aa480512.aspx – SirMoreno

関連する問題