并行WCF调用多个服务器

时间:2010-04-01 19:39:54

标签: .net wcf reflection parallel-processing

我有一个在多个服务器上运行的WCF服务(同一个),我想从一个客户端并行调用所有实例。我正在使用ChannelFactory和接口(契约)来调用服务。每个服务都在.config文件中定义了本地<endpoint>客户端。

我正在尝试做的是构建某种通用框架以避免代码重复。

例如,单个线程中的同步调用如下所示:

    Dim remoteName As String = "endpointName1"
    Dim svcProxy As ChannelFactory(Of IMyService) = New ChannelFactory(Of IMyService)(remoteName)
    Try
        svcProxy.Open()
        Dim svc As IMyService = svcProxy.CreateChannel()
        nodeResult = svc.TestRemote("foo")
    Finally
        svcProxy.Close()
    End Try

我遇到困难的部分是如何指定并实际调用实际的远程方法(例如“TestRemote”)而不必复制上面的代码,以及调用每个方法的所有线程相关的东西

最后,我希望能够编写代码(考虑这个伪代码):

Dim results as Dictionary(Of Node, ExpectedReturnType) 
results = ParallelInvoke(IMyService.SomeMethod, parameter1, parameter2) 

其中ParallelInvoke()将该方法作为参数,以及参数(paramArray或object()...等)然后在每个远程节点上运行请求,阻塞直到它们都返回一个答案或超时,然后将结果返回到以字符串作为节点的字典,并将值作为返回的值。

然后我可以(取决于方法)选择我需要的单个值,或者将每个服务器的所有值聚合在一起,等等。

我很确定我可以使用反射和InvokeMember()来做到这一点,但这需要将方法作为字符串传递(这可能导致错误,例如调用在编译时无法捕获的不存在的方法),所以我想看看是否有更清洁的方法来做到这一点。

由于

2 个答案:

答案 0 :(得分:3)

 public static TResult MakeCall<TService, TResult>(Func<TService, TResult> method,  string remoteName)
        {
            // try not to create the factory object for each call, it can be a singleton
            var factory = GetFactory<TService>(remoteName);
            TService proxy = default(TService);
            TResult result = default(TResult);
            try
            {
                proxy = factory.CreateChannel();
                result = method(proxy);
            }
            finally
            {
                // proxy disposal is a bit tricky in WCF and you might need to read more about Close/Abort
                 Close(proxy);                    

            }
            return result;
        }

允许您在任何接口上调用任何方法,而无需复制管道代码。

public interface IMyService
        {
            int Sum(int a, int b);
            int Max(int a, int b);
        }

公共接口IMyService2             {                 bool Test(字符串值);             }

   static void Main(string[] args)
        {
            var a = 12;
            var b = 12;
            var r1 = MakeCall((IMyService proxy) => proxy.Sum(a, b),  "endpoint1");
            var a1 = 12;
            var b1 = 14;
            var r2 = MakeCall((IMyService proxy) => proxy.Max(a1, b1), "endpoint1");
            var r3 = MakeCall((IMyService2 proxy) => proxy.Test("test"), "endpoint2");
        }

您可以将MakeCall用作最终解决方案的构建块。

答案 1 :(得分:1)

一种方法是使用:

System.Threading.ThreadPool.QueueUserWorkItem(...)

在这里查看VB语法: http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

将aysnc代码放在WaitCallback中。