0

私は最近、WCF でサービスを作成するために、MSDN のチュートリアルHEREに従いました。私の懸念は、CalculatorWindowServiceFromで宣言された変数にアクセスしCalculatorServiceて、後で使用するためにその値を変更できるようにCalculatorWindowServiceする方法です。List<double> DoubleListCalculatorWindowService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ComponentModel;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration;
using System.Configuration.Install;

namespace Microsoft.ServiceModel.Samples
{
    // Define a service contract.
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);
    }

    // Implement the ICalculator service contract in a service class.
    public class CalculatorService : ICalculator
    {
        // Implement the ICalculator methods.
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            return result;
        }

        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            return result;
        }

        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            return result;
        }

        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            return result;            
        }
    }

    public class CalculatorWindowsService : ServiceBase
    {
        public List<double> DoubleList = new List<int>();
        public ServiceHost serviceHost = null;
        public CalculatorWindowsService()
        {
            // Name the Windows Service
            ServiceName = "WCFWindowsServiceSample";
        }

        public static void Main()
        {
            ServiceBase.Run(new CalculatorWindowsService());
        }

        // Start the Windows service.
        protected override void OnStart(string[] args)
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
            }

            // Create a ServiceHost for the CalculatorService type and 
            // provide the base address.
            serviceHost = new ServiceHost(typeof(CalculatorService));

            // Open the ServiceHostBase to create listeners and start 
            // listening for messages.
            serviceHost.Open();
        }

        protected override void OnStop()
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
                serviceHost = null;
            }
        }
    }

    // Provide the ProjectInstaller class which allows 
    // the service to be installed by the Installutil.exe tool
    [RunInstaller(true)]
    public class ProjectInstaller : Installer
    {
        private ServiceProcessInstaller process;
        private ServiceInstaller service;

        public ProjectInstaller()
        {
            process = new ServiceProcessInstaller();
            process.Account = ServiceAccount.LocalSystem;
            service = new ServiceInstaller();
            service.ServiceName = "WCFWindowsServiceSample";
            Installers.Add(process);
            Installers.Add(service);
        }
    }
}
4

1 に答える 1

4

GUI (クライアント) アプリケーションが Windows サービスと対話できるようにするには、プロセス間通信メカニズムを使用する必要があります。これは、Windows サービスと GUI の両方がスタンドアロンの独立したプロセスであるためです。NetNamedPipe最も簡単な方法は、 usingを作成することWindows Communication Foundationです。

パート I: Windows サービス

既に Windows サービスを作成しており、その展開方法を知っていることを前提としています。そこで、Windows サービス プロジェクトにコントラクトを追加することから始めますICalculatorService(このインターフェイスが独自のファイルにあることを確認してください)。

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract]
    void Add(double value);

    [OperationContract]
    List<double> GetAllNumbers();
}

次に、このインターフェースを実装する必要があります。という名前の新しいクラスを (ここでも独自のファイルに) 作成しますCalculatorService

public class CalculatorService: ICalculatorService
{
    private static List<double> m_myValues = new List<double>();

    public void Add(double value)
    {
        m_myValues.Add(value);
    }

    public List<double> GetAllNumbers()
    {
        return m_myValues;
    }
}

static List<double>すべての値を保持するがあることに注意してください。ここで、クライアント (GUI) が接続できるように、Windows サービスをホストにする必要があります。Windows サービスの分離コードは次のようになります。

partial class CalculatorWindowsService : ServiceBase
{
    public ServiceHost m_host;

    public CalculatorWindowsService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        // If the host is still open, close it first.
        if (m_host != null)
        {
            m_host.Close();
        }

        // Create a new host
        m_host = new ServiceHost(typeof(CalculatorService), new Uri("net.pipe://localhost"));

        // Note: "MyServiceAddress" is an arbitrary name. You can change it to whatever you want.
        m_host.AddServiceEndpoint(typeof(ICalculatorService), new NetNamedPipeBinding(), "MyServiceAddress");

        m_host.Open();
    }

    protected override void OnStop()
    {
        // Close the host when the service stops
        if (m_host != null)
        {
            m_host.Close();
            m_host = null;
        }
    }
}

Windows サービス側で必要なのはこれだけです。

パート II: GUI (クライアント) まず、Windows サービスで作成したものと同様のコントラクトを作成して、クライアントがサービス呼び出しを正常に実行できるようにする必要があります。これを行うには、ICalculatorServiceインターフェイスをクライアント アプリケーションにコピーするだけです。クライアントの他のクラスと一致するように、名前空間を変更してください。Add ValueGet All ValuesWindows Formsの 2 つのボタンを持つ単純なプログラムを作成しました。このフォームのコード ビハインドは次のようになります。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    }

    private void AddValue_Click(object sender, EventArgs e)
    {
        using (ChannelFactory<ICalculatorService> facotry = new ChannelFactory<ICalculatorService>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyServiceAddress")))
        {
            ICalculatorService proxy = facotry.CreateChannel();

            // Generate a random number to send to the service
            Random rand = new Random();
            var value = rand.Next(3, 20);

            // Send the random value to Windows service
            proxy.Add(value);
        }
    }

    private void GetAllValues_Click(object sender, EventArgs e)
    {
        using (ChannelFactory<ICalculatorService> facotry = new ChannelFactory<ICalculatorService>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyServiceAddress")))
        {
            ICalculatorService proxy = facotry.CreateChannel();

            // Get all the numbers from the service
            var returnedResult = proxy.GetAllNumbers();

            // Display the values returned by the service
            MessageBox.Show(string.Join("\n", returnedResult));
        }
    }
}

以下は、Windows サービスと WinForms プロジェクトの私のファイルのスナップショットで、どこにあるかを確認するのに役立ちます。

ここに画像の説明を入力

編集を に 変更しm_myValuesて、クラスpublic内でアクセスできます。CalculatorWindowsService

于 2013-08-14T21:44:19.090 に答える