c# - 프로젝트 - two.Net 응용 프로그램 간의 효율적인 통신




윈도우 프로그램 만들기 (2)

저는 현재 C #에서 .Net 응용 프로그램을 작성 중이며 두 가지 주요 구성 요소가 있습니다.

  1. DataGenerator - 많은 양의 데이터를 생성하는 구성 요소
  2. 뷰어 - 생성기에서 생성 한 데이터를 시각화 할 수있는 WPF 응용 프로그램

이 두 구성 요소는 현재 내 솔루션에서 두 개의 개별 프로젝트입니다. 또한 PRISM 4.0 프레임 워크를 사용하여 해당 구성 요소에서 모듈을 만들었습니다.

본질적으로 DataGenerator는 많은 양의 데이터를 생성하고 PRISM의 EventAggregator 를 사용하여 이벤트를 전송하며 뷰어는 이러한 이벤트를 구독하고 사용자가 사용할 수있는 데이터를 표시합니다.

이제 나의 요구 사항이 약간 변경되었고 두 구성 요소가 이제 자신의 응용 프로그램에서 실행됩니다 (그러나 동일한 컴퓨터에서 실행). 나는 여전히 모든 커뮤니케이션을 이벤트 중심으로하고 싶습니다. 그리고 저는 여전히 PRISM 프레임 워크를 사용하고 싶습니다.

내 첫 번째 생각은 두 응용 프로그램 간의 통신을 위해 WCF 를 사용하는 것이 었습니다. 그러나 인생을 조금 더 어렵게 만드는 한 가지가 있습니다.

  1. DataGenerator는 뷰어에 대한 지식 이 전혀 없으며 ( 종속성이 없음 )
  2. 뷰어를 열지 않았거나 뷰어 응용 프로그램을 닫을 경우 DataGenerator는 여전히 완벽하게 작동해야합니다.
  3. 현재 EventAggregator를 사용하여 DataGenerator에서 많은 이벤트가 발생하고 있습니다. WCF는 매우 짧은 시간에 많은 이벤트를 처리 할만큼 효율적입니까?

기본적으로 모든 이벤트가 수행하는 데이터는 매우 간단한 문자열, 정수 및 부울입니다. WCF없이이 작업을 수행하는 데 좀 더 가벼운 방법이있을 수 있습니까?

마지막으로, DataGenerator가 이러한 이벤트를 보낼 수 있고 둘 이상의 어플리케이션이 잠재적으로 하나 이상의 어플리케이션을 등록 할 수 있다면 좋을 것입니다.

모든 제안 및 힌트를 높이 평가합니다.

감사! 신자

EDIT 1

나는 이제 WCF와 콜백을 사용하여 두 개의 간단한 콘솔 응용 프로그램 (하나는 서비스 호스팅 및 메시지 전송, 다른 하나는 메시지 수신)을 작성하고 있습니다 (제안 된대로). 이 코드가 작동하자마자 작업 코드를 추가 할 것입니다.

2 번 수정

좋아요 - 간단한 프로그램 실행을 관리했습니다! :) 도와 줘서 고마워! 다음은 클래스와 클래스의 코드 및 그림입니다.

발신자부터 시작하겠습니다.

내 응용 프로그램에서는 보낸 사람이 서비스 인터페이스와 해당 구현을 포함합니다.

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 프로젝트에 추가되었습니다.

이제 수신자 측에 도달 할 수 있습니다.

Sender에서 이미 수행 된 것처럼, 나는 Service Reference를 프로젝트에 추가했다.

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가 자동으로 생성됩니다. 서버 측에서는 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 콜백을 이해할 수 있도록 도와줍니다. 그것은 매우 잘 작성된 코드가 아니며 전적으로 사용되어서는 안됩니다! 그것은 단순한 예제 응용 프로그램입니다.

https://code.i-harness.com







prism