Параллельные вызовы WCF на несколько серверов - PullRequest
0 голосов
/ 01 апреля 2010

У меня есть служба WCF (одна и та же), работающая на нескольких серверах, и я хотел бы вызывать все экземпляры параллельно с одного клиента. Я использую ChannelFactory и интерфейс (контракт) для вызова сервиса. У каждой службы есть локальный клиент <endpoint>, определенный в файле .config.

То, что я пытаюсь сделать, - это создать некую общую структуру, чтобы избежать дублирования кода.

Например, синхронный вызов в одном потоке выглядит примерно так:

    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 ]

3 голосов
/ 02 апреля 2010
 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 голос
/ 01 апреля 2010

Один из способов сделать это - использовать:

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

Найдите здесь синтаксис VB: http://msdn.microsoft.com/en-us/library/4yd16hza.aspx

Поместите код aysnc в WaitCallback.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...