2012-04-30 48 views
1

服務器和客戶端使用.NET 4中,異步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