WCF callback机制的应用:实时投票模型

在WCF应用callback模式时,一些指导性的document给出的建议是将callback contract内的operation的Message Exchange Pattern设置为IsOneWay.

当然,当service调用callback而不需要从client instance获得callback的return value的时候,MEP设置为IsOneWay不失为最好的选择了。但是如果在某些应用场景下,我们需要获得客户端callback结果时候,就不能将MEP设置为IsOneWay=true了。

当然,当MEP设置为IsOneWay=false的时候,其他同步设置必须相应match,即ConcurrentMode只能为ReEntrant或者Multiple。

下面给出一个简单的应用模式:在线实时投票。

其简单系统模型如下:

WCF service提供一个简单的投票服务,收集投票结果通过callback机制得到各个client的结果后然后返回给service,然后WCF service给出statistics.

 针对这样的投票模型,在设置service的时候需要注意的是:

1.callback contract中的operation一定要设置为IsOneWay=false。否则callback无法return至服务端

2.ConcurrentMode不能设置为Single,而只能为ReEntrant或者Multiple.

3. 当service callbacks client的时候,callback result的处理权在service,比如对结果进行统计处理等等。

下面给出主要的source code:

callback contract和service contract的定义

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

namespace WCFCallBack
{
    [ServiceContract]
    
public interface ICaculatorCallBack
    {
        [OperationContract]
        
int Equals(int result);
    }

    [ServiceContract(CallbackContract
=typeof(ICaculatorCallBack))]   
    
public interface ICaculatorService
    {
        [OperationContract]
        
void AddTo(int n);

        [OperationContract]
        
void Register();
    }
}

servicecontract implementation以及消息发布

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

namespace WCFCallBack
{
    
public class AddEventAgrs : EventArgs
    {
       
public int result;
    }

    [ServiceBehavior(ConcurrencyMode
=ConcurrencyMode.Reentrant)]
    
class CaculatorService:ICaculatorService
    {
        
public delegate void AddEventHandler(object sender, AddEventAgrs e);
        
public static event AddEventHandler OnAddCompleted;
        
public ICaculatorCallBack callback;
        
public int result;

        
public CaculatorService()
        {
            result 
= 0;
            Console.WriteLine(
"A Calculator Instance is constructed");
        }

        
public void Register()
        {
            callback 
= System.ServiceModel.OperationContext.Current.GetCallbackChannel<ICaculatorCallBack>();
            OnAddCompleted 
+= new AddEventHandler(CaculatorService_OnAddCompleted);
        }


        
void CaculatorService_OnAddCompleted(object sender, AddEventAgrs e)
        {
            Console.WriteLine(
"the OnAdd event has been triggered");
            Console.WriteLine(
"the callback result from client is "+callback.Equals(e.result));

        }

        
public void BroadAddEvent(AddEventAgrs e, AddEventHandler temp)
        {
            
if (OnAddCompleted != null)
            {
                
foreach (AddEventHandler handler in temp.GetInvocationList())
                {
                    handler.BeginInvoke(
this, e, nullnull);
                }
            }
        }
       
        
public void AddTo(int n)
        {
            AddEventAgrs e 
= new AddEventAgrs();
            
this.result += n;
            e.result 
= result;
            BroadAddEvent(e, OnAddCompleted);
        }
    }
}

client1 callback实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WCFClient
{
    
class CallBack:ICaculatorServiceCallback
    {
        
public int Equals(int n)
        {
            
//Console.WriteLine("haha");
            Console.WriteLine("this callback is implemented on client,the callback result is {0}", n.ToString());
            
return 2*n ;
        }
    }
}

client2 callback implementation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WCFClient
{
    
class CallBack:ICaculatorServiceCallback
    {
        
public int Equals(int n)
        {
            Console.WriteLine(
"I have received a broadcasting news,the callback result is {0}", n.ToString());
            System.Threading.Thread.Sleep(
2000);
            
return n * n;
        }
    }
}

运行结果:

service screenshot

client1 screenshot

client 2 screenshot

原文地址:https://www.cnblogs.com/Winston/p/1345647.html