Подтвердить что ты не робот

Эффективная связь между двумя приложениями .Net

В настоящее время я пишу приложение .Net в С#, которое имеет два основных компонента:

  • DataGenerator - компонент, генерирующий много данных.
  • Viewer - приложение WPF, способное визуализировать данные, которые создает генератор.

Эти два компонента в настоящее время являются двумя отдельными проектами в моем решении. Кроме того, я использую структуру PRISM 4.0, чтобы сделать модули из этих компонентов.

По сути, DataGenerator генерирует много данных и отправляет события с помощью EventAggregator из PRISM, и программа просмотра подписывается на эти события и показывает данные, готовые для пользователя.

Теперь мои требования немного изменились, и два компонента теперь будут запускаться в собственном приложении (но на том же компьютере). Я все равно хотел бы, чтобы все связанные с событиями события были связаны, и я также хотел бы использовать инфраструктуру PRISM.

Моя первая мысль заключалась в использовании WCF для связи между этими двумя приложениями. Однако есть одна вещь, которая делает жизнь немного сложнее:

  • DataGenerator не имеет абсолютно никаких знаний о Viewer (и никаких зависимостей)
  • DataGenerator все равно должен работать отлично, если мы не открываем просмотр или закрываем приложение для просмотра.
  • в DataGenerator (с помощью EventAggregator) растет много событий: достаточно ли WCF для обработки множества событий за очень короткий промежуток времени?

В принципе, данные, которые переносятся все эти события, представляют собой очень простые строки, integer и booleans. Может ли быть более легкий способ сделать это без WCF?

Наконец, было бы неплохо, если бы DataGenerator мог отправлять эти события и потенциально более одного приложения подписывалось на них (или ничего).

Любые предложения и советы приветствуются.

Спасибо! Christian

РЕДАКТИРОВАТЬ 1

Теперь я создаю два простых консольных приложения (один из которых размещает службу и отправляет сообщения, другой - сообщения) с использованием WCF и обратных вызовов (как было предложено). Я добавлю рабочий код, как только я получу эту работу.

РЕДАКТИРОВАТЬ 2

Хорошо - удалось запустить простую программу!:) Спасибо за помощь ребята! Вот код и изображение того, где находятся классы:

enter image description here

Начните с отправителя:

В моем приложении отправитель содержит интерфейсы служб и их реализации.

IMessageCallback - это интерфейс обратного вызова:

namespace WCFSender
{
    interface IMessageCallback
    {
        [OperationContract(IsOneWay = true)]
        void OnMessageAdded(string message, DateTime timestamp);
    }
}

ISimpleService - это контракт на обслуживание:

namespace WCFSender
{
    [ServiceContract(CallbackContract = typeof(IMessageCallback))]
    public interface ISimpleService
    {
        [OperationContract]
        void SendMessage(string message);

        [OperationContract]
        bool Subscribe();

        [OperationContract]
        bool Unsubscribe();
    }
}

SimpleService - это реализация ISimpleService:

public class SimpleService : ISimpleService
    {
        private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();

        public void SendMessage(string message)
        {
            subscribers.ForEach(delegate(IMessageCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnMessageAdded(message, DateTime.Now);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        public bool Subscribe()
        {
            try
            {
                IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
                if (!subscribers.Contains(callback))
                    subscribers.Add(callback);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Unsubscribe()
        {
            try
            {
                IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
                if (!subscribers.Contains(callback))
                    subscribers.Remove(callback);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }

В Program.cs(со стороны отправителя) Служба размещается и отправляются сообщения:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    class Program : SimpleServiceReference.ISimpleServiceCallback, IDisposable
    {
        private SimpleServiceClient client;

        static void Main(string[] args)
        {
            ServiceHost myService = new ServiceHost(typeof(SimpleService));
            myService.Open();
            Program p = new Program();
            p.start();

            Console.ReadLine();
        }

        public void start()
        {
            InstanceContext context = new InstanceContext(this);

            client = new SimpleServiceReference.SimpleServiceClient(context, "WSDualHttpBinding_ISimpleService");

            for (int i = 0; i < 100; i++)
            {
                client.SendMessage("message " + i);
                Console.WriteLine("sending message" + i);
                Thread.Sleep(600);
            }
        }

        public void OnMessageAdded(string message, DateTime timestamp)
        {
            throw new NotImplementedException();
        }

        public void Dispose()
        {
            client.Close();
        }
    }

Кроме того, обратите внимание, что ссылка на службу была добавлена ​​в проект отправителя!

Теперь перейдите на сторону приемника:

Как уже было сделано в Sender, я добавил ссылку на службу в проект.

Существует только один класс, Program.cs:

[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    class Program : SimpleServiceReference.ISimpleServiceCallback, IDisposable
    {
        private SimpleServiceClient client;

        static void Main(string[] args)
        {
            Program p = new Program();
            p.start();
            Console.ReadLine();
            p.Dispose();
        }

        public void start()
        {
            InstanceContext context = new InstanceContext(this);

            client = new SimpleServiceReference.SimpleServiceClient(context, "WSDualHttpBinding_ISimpleService");
            client.Subscribe();
        }

        public void OnMessageAdded(string message, DateTime timestamp)
        {
            Console.WriteLine(message + " " + timestamp.ToString());
        }

        public void Dispose()
        {
            client.Unsubscribe();
            client.Close();
        }
    }

Последнее, что осталось, это файлы app.config. На стороне клиента app.config автоматически создается путем добавления служебной ссылки. На стороне сервера я немного изменил конфигурацию, однако ее части также автоматически генерируются путем добавления служебной ссылки. Обратите внимание, что вам необходимо внести изменения перед добавлением служебной ссылки:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsDualHttpBinding>
                <binding name="WSDualHttpBinding_ISimpleService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00" />
                    <security mode="Message">
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" />
                    </security>
                </binding>
            </wsDualHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8732/Design_Time_Addresses/WCFSender/SimpleService/"
                binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_ISimpleService"
                contract="SimpleServiceReference.ISimpleService" name="WSDualHttpBinding_ISimpleService">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
        <behaviors>
            <serviceBehaviors>
                <behavior name="MessageBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service name="WCFSender.SimpleService" behaviorConfiguration="MessageBehavior">
                <endpoint address="" binding="wsDualHttpBinding" contract="WCFSender.ISimpleService">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8732/Design_Time_Addresses/WCFSender/SimpleService/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
    </system.serviceModel>
</configuration>

ВАЖНО: Мне удалось реализовать эти два очень простых приложения, используя учебные пособия. Вышеприведенный код работает для меня и, надеюсь, помогает другим понять обратный вызов WCF. Это не очень хорошо написанный код и не должен использоваться полностью! Это просто упрощенное приложение.

4b9b3361

Ответ 1

Не беспокойтесь о производительности, wcf может достичь очень высокой пропускной способности при правильной настройке. Используйте обратные вызовы для ваших событий: http://www.switchonthecode.com/tutorials/wcf-tutorial-events-and-callbacks

Ответ 3

Используйте Microsoft StreamInsight 1.2. В примерах использования описывается, что он может внедряться в приложение, службу WCF или и то, и другое.

Прочитайте статью MSDN abou StreamInsight 1.2:

Microsoft® StreamInsight - это сложная обработка событий в Microsoft технологии, помогающие компаниям создавать приложения, управляемые событиями, и получить более точную информацию, сопоставляя потоки событий с несколькими источники с минимальной задержкой.

Microsoft StreamInsight ™ - это мощная платформа, которую вы можете использовать для разрабатывать и развертывать сложные приложения обработки событий (CEP). это архитектуры с высокой пропускной способностью и Microsoft.NET Рамочная платформа разработки позволяет быстро реализовать надежных и высокоэффективных приложений обработки событий. Мероприятие источники потока обычно включают данные из производственных приложений, финансовые торговые приложения, веб-аналитика и операционные аналитика. Используя StreamInsight, вы можете разрабатывать приложения CEP которые получают немедленную ценность для бизнеса из этих необработанных данных за счет сокращения стоимость извлечения, анализа и корреляции данных; и позволяя вам контролировать, управлять и обрабатывать данные для условий, возможности и дефекты почти мгновенно.

Используя StreamInsight для разработки приложений CEP, вы можете достичь следующие тактические и стратегические цели для вашего бизнеса:

  • Мониторинг данных из нескольких источников для значимых шаблонов, тенденции, исключения и возможности.

  • Анализировать и коррелировать данные постепенно, пока данные в полете, т.е. без его первого хранения - очень низко задержка. Совокупные, казалось бы, несвязанные события из разных источников и выполнять сложные анализы с течением времени.

  • Управляйте своим бизнесом с помощью аналитики с низкой задержкой на событий и срабатывания ответных действий, которые определены на вашем показатели эффективности ключевых показателей бизнеса (KPI).

  • Быстро реагировать на области возможностей или угрозы путем включения ваши определения KPI в логику приложения CEP, тем самым повышение эффективности работы и способность быстро реагировать к возможностям бизнеса.

  • События шахт для новых KPI для бизнеса.

  • Переход к прогнозной бизнес-модели путем анализа исторических данных постоянно совершенствовать и улучшать определения KPI.

Дополнительная информация и образцы можно найти на CodePlex: