0

我最近关注了 MSDN 教程HERE为了使用 WCF 提供服务。我现在关心的是如何访问在CalculatorWindowServiceFrom中声明的变量,CalculatorService以便我可以修改它的值以供以后使用CalculatorWindowService例如,如果在 Add、Subtract、Divide 和 Multiply 方法中,如果我还希望将结果存储到List<double> DoubleList声明的在CalculatorWindowService

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 都是独立的、独立的进程。最简单的方法是创建一个NetNamedPipeusing Windows Communication Foundation.

第一部分: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>包含所有值的 a。现在,我们需要使 Windows 服务成为主机,以便客户端 (GUI) 可以连接到它。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 服务端所需要的。

第二部分:GUI(客户端) 首先,我们需要确保我们创建的合约与我们在 Windows 服务中创建的合约一样,以便客户端能够成功地进行服务调用。为此,只需将ICalculatorService接口复制到客户端应用程序。确保更改命名空间,使其与客户端中的其他类一致。我创建了一个Windows Forms带有两个按钮的简单程序:Add ValueGet All Values。此表单背后的代码如下所示:

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 回答