Windows 服务和 Windows 窗体应用程序之间的通信

Posted

技术标签:

【中文标题】Windows 服务和 Windows 窗体应用程序之间的通信【英文标题】:Communication between Windows service and Windows form application 【发布时间】:2014-01-04 09:54:35 【问题描述】:

我正在做一个文件上传器的项目。在项目中,有一些由应用程序创建并保存在特定文件夹中的日志文件。这些文件的内容始终是文本。这些文件的内容被上传到服务器,这个任务由 Windows 服务完成。服务会一一读取文件,然后将其内容传输到服务器。

以前,此任务过去由应用程序本身完成。但它与应用程序分开,因为当应用程序运行时用户可能处于脱机状态。因此这些文件将保持等待上传。

使用服务的好处是显而易见的,用户不必担心上传的事情。每当用户连接到互联网时,该服务都会处理它。

现在的要求是,当服务上传文件的内容并且创建文件的应用程序正在运行时,服务应该向应用程序发送一条消息,告诉应用程序正在上传哪个文件的内容。

现在的问题是服务和应用程序没有通信。我已经从使用命名管道进行通信的服务和应用程序中产生了单独的线程。

这是我尝试过的代码。

服务代码:

public partial class Service : ServiceBase

Thread t;
    public Service()
    
        InitializeComponent();
    

    protected override void OnStart(string[] args)
    
        File.WriteAllText("D:\\log.txt", "Service started.\n");
        ThreadStart ts = new ThreadStart(Connection);
        t = new Thread(ts);
        t.Start();
    

    void Connection()
    
        NamedPipeServerStream server = new NamedPipeServerStream("server");
        server.WaitForConnection();
        File.WriteAllText("D:\\log.txt", "Connection established.");
    

    protected override void OnStop()
    
        if (t.IsAlive)
        
            t.Abort();
            File.AppendAllText("D:\\log.txt", "Service stopped.");
        
    

应用代码:

public delegate void SendMsg(string s);
public partial class UI : Form

    Thread t;

    public UI()
    
        InitializeComponent();
    

    private void UI_Load(object sender, EventArgs e)
    
        lblStatus.Text = "Waiting...";
        ThreadStart ts = new ThreadStart(Connection);
        t = new Thread(ts);
        t.Start();
    

    void DisplayMsg(string s)
    
        lblStatus.Text = s;
    

    void Connection()
    
        try
        
            NamedPipeClientStream client = new NamedPipeClientStream("server");
            SendMsg msg = new SendMsg(DisplayMsg);
            msg("Connecting...");
            client.Connect();
            msg("Connected");
        
        catch (Exception ex)
        
            File.WriteAllText("D:\\log.txt", ex.Message);
        
    

这段代码有什么问题?

如果我使用另一个表单应用程序代替服务,则相同的逻辑可以工作。

在谷歌搜索时,我了解到 Windows Vista 及更高版本中的会话 0,它专门用于 Windows 服务,并与登录用户使用的其他会话隔离。我在我的系统中使用 Windows 8。这会是个问题吗?请详细说明。

【问题讨论】:

MMF 有什么问题?它们比命名管道更快,并且没有命名管道的故障。 代码完全被破坏了。它尝试创建 两个 服务器,使用计时器重复。并在客户端读取数据之前删除数据。摆脱计时器,这没有任何意义。只创建一次管道服务器。 不知道为什么要关闭投票。对于 SO,这似乎是一个非常有效的问题。 我已经编辑了我的问题。我删除了计时器并仅使用了命名管道。但是服务和应用程序仍然没有通信。 【参考方案1】:

我承认我不是命名管道方面的专家。我对他们的唯一经验是通过Windows Communication Foundation (WCF),我遇到过他们的间歇性问题,尽管可能是因为我做错了什么。所以我不能聪明地谈论你的命名管道问题。我确实知道,当Hans Passant 提出建议时,通常最好听一听。

话虽如此,如果您希望通信要求保持简单,那么使用命名管道(套接字、内存映射文件等)没有任何问题。当然,如果服务和应用程序之间的通信预计会增长,那么考虑像 WCF 这样更正式的东西可能是有意义的。

【讨论】:

以上是关于Windows 服务和 Windows 窗体应用程序之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

Windows 窗体应用程序包括 .net 框架

Windows 服务和 Windows 窗体应用程序之间的通信

什么是最佳选择,Windows 窗体或 C# 中的 WPF 开发?

Windows 服务与 Windows 窗体在同一进程中

在 Windows 服务和窗体应用程序之间使用套接字进行进程间通信

ASP.NET 网站 + Windows 窗体应用程序 + WCF 服务:客户端凭据