【问题标题】:Asynchronous Web Service Callbacks - How to implement with two function on the server side异步 Web 服务回调 - 如何在服务器端使用两个函数实现
【发布时间】:2012-04-30 07:10:24
【问题描述】:

服务器和客户端都使用.Net 4,

目前正在使用回调来进行异步 Web 服务调用。

但是服务器做的工作需要很长时间,我希望能够释放服务器上的请求线程(类似于客户端)。

是否可以使用 .Net Callbacks 来调用服务器上的函数 A。

而函数B(在服务器上)会将答案返回给客户端回调函数?

我正在使用Asynchronous Web Service Calls over HTTP with the .NET Framework(没有 WCF)。

谢谢

拉斐尔

【问题讨论】:

    标签: .net web-services asynchronous


    【解决方案1】:

    在此示例代码中,客户端调用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);
                       }
    
                    });
            }
        }
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2011-09-03
    • 2018-01-13
    • 1970-01-01
    相关资源
    最近更新 更多