使用 Windows 服务本地托管的 WCF 服务 - 与 GUI 的命名管道通信 - “管道已结束。(109, 0x6d)。”

问题描述 投票:0回答:1

我已经阅读了 Microsoft 页面上有关 Windows 平台上进程间通信的文档,因此我开始做一些演示项目来测试它是如何工作的等。因为我想做的就是将一些文件从 Windows 共享从本地网络复制到我决定选择

WPF
作为 GUI 和一些“其他”方法来完成逻辑工作。

我的想法是实现GUI和Windows Service之间的成功通信。在 MSDN 上,我在堆栈上的其他帖子中阅读并发现最好的方法是使用 Windows Communication Foundation。

问题

通讯已建立。我已经准备好了一个正在运行的端点。返回一小部分数据是可以的,但是当执行一些更复杂的操作(例如循环遍历 NFS 共享或目录中的某些文件)时,则会抛出异常

'There was an error reading from the pipe: The pipe has ended. (109, 0x6d).'

这是我的项目结构(4个解决方案):

  • Windows 服务 - 托管 WCFService,
  • WCFService - 包括具有可供 GUI 调用的“可用”方法的接口和类,
  • 共享类库 - 包括逻辑类、应用程序设置、“模型”,如
    DirToCopy
  • GUI - 用于检查共享目录和列表以及可用于“复制”的目录的简单按钮。

Windows 服务和 WCFService:

  • app.config(两边配置相同):

    <system.serviceModel>
            <services>
                <service name="WCFService.MyService">
                    <endpoint address="net.pipe://localhost/copy" binding="netNamedPipeBinding"
                        bindingConfiguration="" contract="WCFService.IMyService" />
                </service>
            </services>
    </system.serviceModel>

Windows服务:

  • MyServiceHost.cs:

    protected override void OnStart(string[] args)
            {
                if (serviceHost != null)
                {
                    serviceHost.Close();
                }
    
                serviceHost = new ServiceHost(typeof(MyService));
                serviceHost.Open();
            }
    
            protected override void OnStop()
            {
                if (serviceHost != null)
                {
                    serviceHost.Close();
                    serviceHost = null;
                }
            }

WCF服务:

  • IMyService.cs:

    [ServiceContract]
        public interface IMyService
        {   
            //In SharedClasses solution. Included in using.    
            [OperationContract]
            MyServiceSettings GetSettings();
    
            //In SharedClasses solution. Included in using.
            [OperationContract]
            List<DirToCopy> GetDirs();
        }

  • MyService.cs:

    public class MyService : IMyService
        {
            // SharedClasses lib
            private MyServiceSettings Settings;
            // SharedClasses lib
            private DirToCopyService DirService;
    
            public MyService()
            {
                Settings = new MyServiceSettings();
                DirService = new DirService(Settings);
            }
    
            public MyServiceSettings GetSettings()
            {
                return Settings;
            }
    
            public List<DirToCopy> GetDirs()
            {
                return DirService.GetDirs();
            }
        }

共享类库:

  • DirToCopyService.cs:

    public class DirToCopyService
        {
            private MyServiceSettings _Settings;
            public List<DirToCopy> dirs;
    
            public DirToCopyService() { }
    
            public DirToCopyService(MyServiceSettings Settings) 
            {
                _Settings = Settings;
            }
    
            public List<DirToCopy> GetDirs()
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(_Settings.nfsAddress);
    
                FileInfo[] files = directoryInfo.GetFiles("*.txt");
    
                dirs = new List<DirToCopy>();
    
                foreach(FileInfo file in files)
                {
                    DirToCopy dirToCopy = new DirToCopy();
                    dirToCopy._filename = file.FullName;
                    dirToCopy._size = new System.IO.FileInfo(Path.Combine(_Settings.nfsAddress, file.FullName)).Length;
                    dirs.Add(DirToCopy);
                }
                return dirs;
            }
        }

图形用户界面:

  • ServiceClient.cs:

    public class ServiceClient
        {
            private IMyService _serviceProxy;
            private ChannelFactory<IMyService> _channelFactory;
            private const string NamedPipeAddress = "net.pipe://localhost/copy";
    
            public ServiceClient()
            {
                _channelFactory = new ChannelFactory<IMyService>(new NetNamedPipeBinding(), new EndpointAddress(NamedPipeAddress));
                _serviceProxy = _channelFactory.CreateChannel();
            }
            
            public MyServiceSettings GetSettings()
            {
                return _serviceProxy.GetSettings();
            }
    
            public List<DirToCopy> GetDirs()
            {
                return _serviceProxy.GetDirs();
            }
    
        }

  • MainViewModel.cs:我在这里创建 ServiceClient 的实例并将其传递给 DirsToCopyVM(视图模型)。然后处理调用
    GetDirs()
    的按钮单击并抛出“管道”错误。

总结: GUI 初始化后,

MyServiceSettings
已正确传递给它,我可以在 GUI 中使用此类的任何属性。但是当我想做一些更复杂的事情,比如检索
List<DirsToCopy>
时,在专用于
Click
方法的操作处理之后,就会出现错误:
'There was an error reading from the pipe: The pipe has ended. (109, 0x6d).'

我不知道这是否是由于传递的数据大小或任何其他设置引起的。我也不确定我的方法是否正确或者我应该改变它。有人有类似问题吗

c# wpf wcf ipc named-pipes
1个回答
0
投票

如果它适用于较小部分的数据,您可以尝试增加绑定的一些配额,例如:

<system.serviceModel>
  <bindings>
    <netNamedPipeBinding>
      <binding name="netNamedPipeBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" />
    </netNamedPipeBinding>
  </bindings>
  <services>
    <service name="WCFService.MyService">
      <endpoint address="net.pipe://localhost/copy" binding="netNamedPipeBinding"
          bindingConfiguration="netNamedPipeBinding" contract="WCFService.IMyService" />
    </service>
  </services>
</system.serviceModel>

您可能还想更改传输模式:

神秘 => 从管道读取错误:管道已结束。 (109, 0x6d)

© www.soinside.com 2019 - 2024. All rights reserved.