Эффективная связь между двумя приложениями .Net - PullRequest
15 голосов
/ 04 октября 2011

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

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

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

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

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

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

  1. DataGenerator абсолютно не знает о средстве просмотра ( и без зависимостей )
  2. DataGenerator по-прежнему должен работать безупречно, если у нас нет открытого средства просмотра или если мы закрываем приложение средства просмотра.
  3. В настоящее время из DataGenerator (с использованием EventAggregator) возникает много событий:Достаточно ли эффективен WCF для обработки большого количества событий за очень короткий промежуток времени?

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

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

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

Спасибо!Кристиан

РЕДАКТИРОВАТЬ 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();
        }
    }

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

Теперь перейдем на сторону получателя:

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

Существует только один класс 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.Это не очень хорошо написанный код и не должен использоваться полностью!Это просто упрощенный пример приложения.

Ответы [ 3 ]

7 голосов
/ 04 октября 2011

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

4 голосов
/ 04 октября 2011

Используйте WCF с обратными вызовами, это очень эффективно при правильной настройке.

Вот некоторые тесты: http://msdn.microsoft.com/en-us/library/bb310550.aspx

Вот хороший пример использования обратных вызовов: http://idunno.org/archive/2008/05/29/wcf-callbacks-a-beginners-guide.aspx

1 голос
/ 05 октября 2011

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

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

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

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

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

  • Контролируйте свои данные из нескольких источников на предмет значимых закономерностей, тенденций, исключений и возможностей.

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

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

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

  • Шахтные события для новых бизнес-показателей KPI.

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

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

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