Winform应用程序与服务通信

时间:2014-04-08 17:27:04

标签: c# wcf service

我需要在C#中编写一个即使没有人登录也会在PC上运行的服务。我需要编写一个ac#winform应用程序,当用户登录并允许用户进行交互时它会自动运行我提出的解决方案是在服务中构建一个WCF服务器,并将一个WCF客户端写入winform应用程序。然后,这将允许Winform应用程序和服务之间的交互。这是最好/最简单的方法吗?

5 个答案:

答案 0 :(得分:4)

是的 - WCF可能是WinForms客户端和服务后端之间通信的最简单解决方案。

您的主要替代方案是:  1. TCP套接字(较低级别,可能需要更多的样板代码)。  2.消息传递中间件,如MSMQ / ActiveMQ NMS(涉及添加更多第三方库)

如果你选择WCF,我的经验会有一些问题/建议:

  1. 不是在服务器中同步处理WCF请求,而是异步处理它们(如果代码是线程安全的),或者通过单个后台处理队列处理它们(如果您的代码不是线程安全的)。这有助于避免超时问题(可能导致WCF出现故障),以及从多个线程同时触发WCF请求的问题。
  2. 不要忘记您可能需要在客户端和服务器中使用WCF接口。如果您希望服务器能够将任何类型的异步通信发送回客户端,则需要这样做。
  3. 您可以使用WCF设置发布/订阅机制,但这有点棘手。这是一个代码示例:
  4. 接口

    //Server interface
    [ServiceContract(CallbackContract = typeof(IGUIService))]
    public interface IServerService
    {
        [OperationContract(IsOneWay = true)]
        void Subscribe();
    
        [OperationContract(IsOneWay = true)]
        void Unsubscribe();
    
        ...
    
    }
    
    //Client interface
    [ServiceContract]
    public interface IGUIService
    {
        [OperationContract(IsOneWay = true)]
        void MessageCallback(string Message);
    }
    

    客户端需要在启动时调用Subscribe(),并在关闭时调用Unsubscribe()。处理此问题的相应服务器代码是:

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class ServerService : IServerService
    {
        internal event SettingsUpdatedHandler SettingsUpdated;
        internal delegate void SettingsUpdatedHandler(ServerService adminPort, EventArgs e);
    
        private static List<IGUIService> Clients = new List<IGUIService>();
    
        public void Subscribe()
        {
                IGUIService callback = OperationContext.Current.GetCallbackChannel<IGUIService>();
                if(!Clients.Contains(callback))
                    Clients.Add(callback);
        }
    
        public void Unsubscribe()
        {
                IGUIService callback = OperationContext.Current.GetCallbackChannel<IGUIService>();
                if (Clients.Contains(callback))
                    Clients.Remove(callback);
        }
    }
    

    然后从服务器向所有连接的客户端发送消息:

        internal void SendMessage(string message)
        {
                for(int i=Clients.Count - 1; i >= 0; i--)
                {
                    IGUIService callback = Clients[i];
                    if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                        callback.MessageCallback(message);
                    else
                        Clients.RemoveAt(i);
                }
        }
    

答案 1 :(得分:1)

如果您还想要,也可以使用web api。但请注意,如果使用web api,您可以使用交易。

但是web api和wcf都很好。

答案 2 :(得分:1)

WCF服务器:托管在服务器中的Windows服务中。

WCF客户端:Winform应用程序。并将程序的快捷方式放在文件夹“C:\ Documents and Settings [username] \ Start Menu \ Programs \ Startup”(Windows XP)中。当用户登录时,程序将自动运行。

答案 3 :(得分:1)

您需要维持服务状态吗?如果没有,那么你不能只在IIS中托管或自己托管wcf,web api甚至服务堆栈服务。该服务还将由多个客户使用?持久性存储访问是否需要存在于另一个进程中,如果不是,那么&#34;在进程中#34;也没关系,没有所有服务相关的东西的开销。

答案 4 :(得分:1)

您拥有的是两个需要相互通信的流程。其中一个进程恰好是Windows服务,而另一个进程是Windows应用程序。这是进程间通信的经典问题。有许多可用的解决方案,可能最受欢迎的是:

  1. WCF,你已经提到了。您的Windows服务实现了WCF服务的主机,并且应用程序与公开的服务进行通信。这是一个很好的example如何实现这一点。
  2. 命名管道,老了,很多人喜欢。查看herehere以获取一些示例。
  3. 其他更奇特的例子:

    1. 自定义TCP端口
    2. Win32 RPC。您可以使用.NET包装器,如this库。
    3. MSMQ
    4. 文件系统。一个进程写入定义的位置,另一个进程侦听。您可以使用序列化来编写双方理解的简单消息,甚至是整个对象。
    5. 数据库。第4点的变化,使用提供数据库功能的第三个过程。
    6. 鉴于WCF是一个非常成熟的技术,具有足够的性能,使用.NET构建并且相当容易实现,这似乎是一个自然的选择。