.net 管道抛出错误(尝试在已运行的wpf应用程序上发送命令)

4xy9mtcn  于 2023-01-18  发布在  .NET
关注(0)|答案(1)|浏览(129)

管道抛出错误我无法修复。我想在执行时使用命令管道发送命令行。下面是代码,消息到达没有问题,但抛出错误后:

public MainWindow()
    {
    InitializeComponent();
    _pipeServer = new NamedPipeServerStream("CommandPipe", PipeDirection.In);
    Thread listenThread = new Thread(ListenForCommands);
    listenThread.Start();
    }
 
  private void ListenForCommands()
   {
    while (true)
    {
        if (!_pipeServer.IsConnected)
        {
            _pipeServer.WaitForConnection();
        }

        using (StreamReader sr = new StreamReader(_pipeServer))
        {
           
            while (_pipeServer.IsConnected)
            {
                string commandLineArguments = sr.ReadLine();
                if (string.IsNullOrEmpty(commandLineArguments))
                    continue;
                // Process the command line arguments
                ProcessCommand(commandLineArguments);
            }
        }         
    }
}

private void ProcessCommand(string commandLineArguments)
{

    // Your command processing logic here

    MessageBox.Show(commandLineArguments);
    //...
}

错误为系统。对象处理异常:'无法访问关闭的管道。'
发送命令提示符时:
echo您好,世界〉.\pipe\命令管道
正如我之前所说,消息工作正常,但在关闭消息框后抛出该错误。

根据Alex的建议,此处更新了工作代码:

public MainWindow()
    {
        InitializeComponent();
        _pipeWorker = new BackgroundWorker();
        _pipeWorker.DoWork += PipeWorker_DoWork;
        _pipeWorker.RunWorkerAsync();
    }
   
   private void PipeWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        _pipeServer = new NamedPipeServerStream("CommandPipe", PipeDirection.In);
        while (true)
        {
            _pipeServer.WaitForConnection();
            using (var reader = new StreamReader(_pipeServer))
            {
                string command = reader.ReadLine();
                // Handle the command here
                Dispatcher.Invoke(() => HandleCommand(command));
            }
        }
    }

     private void HandleCommand(string command)
    {
      _pipeServer.Dispose();
      _pipeServer = new NamedPipeServerStream("CommandPipe", PipeDirection.In);

     // do anything you want with the command received
        command = command.TrimEnd();
        switch (command)
        {
            case "quit":
                // Do something
                System.Windows.Application.Current.Shutdown();
                break;
            case "minimize":
                // Do something else
                this.WindowState = WindowState.Minimized;
                break;
            default:
                // Handle unknown command
                break;
        }    
    }

对于仅从Windows命令提示符进行的测试,您可以通过以下方式发送消息:
回显退出〉.\管道\命令管道
回显最小化〉.\管道\命令管道
等等!

thtygnil

thtygnil1#

我猜您使用的是WPF(或者可能是WForms),但不是控制台应用程序,因为你有一个消息框。无论如何,某个地方有main,这个main示例化一个窗口和你的应用程序存在所必需的任何其他东西。它可能以.Run()方法结束,该方法将把你的应用程序的生存期绑定到主窗口的生存期(如果你没有创建任何前台任务,那么在你关闭主窗口后,让程序保持活动状态).无论如何,你的MainWindow()不属于那个家族,一旦侦听器线程启动,它就会返回(完成方法执行).
首先:我不明白为什么要用这种方式创建一个线程,请使用后台工作线程。
第二:你的_pipServer是一个可丢弃的流,它将在MainWindos()的出口结束(被丢弃),等待连接的线程可能会立即看到一个死的(被丢弃的)对象。
查看https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes.namedpipeserverstream?view=net-7.0,了解如何正确示例化管道。示例中的main方法是在应用的整个生命周期中必须存在的所有方法(即作为backgroundWorker的主体)。
为了更好地理解流如何进入和退出方法:使用此代码片段:

public MainWindow()
{
    InitializeComponent();
    _pipeServer = new NamedPipeServerStream("CommandPipe", PipeDirection.In);
    Thread listenThread = new Thread(ListenForCommands);
    listenThread.Start();
    try
    {
        MessageBox.Show($"Leaving Main Windows {DateTime.Now} state of pipe CanRead: {_pipeServer.CanRead});
    }
    catch 
    {
        MessageBox.Show($"Pipe is already dead);
    }
}

private void ListenForCommands()
    {
    int count = 0;
    while (true)
     {
        try 
        {
            MessageBox.Show($"ListenForCommands() iteration {count}. Status of pipe Can Read: {pipeServer.CanRead});
            if (!_pipeServer.IsConnected)
            {
                _pipeServer.WaitForConnection();
            }

            using (StreamReader sr = new StreamReader(_pipeServer))
            {
               
                while (_pipeServer.IsConnected)
                {
                    string commandLineArguments = sr.ReadLine();
                    if (string.IsNullOrEmpty(commandLineArguments))
                        continue;
                    // Process the command line arguments
                    ProcessCommand(commandLineArguments);
                }
            }
        } 
        catch
        {
            MessageBox.Show($"Errors in _pipeServer access from ListenForCommands(). Iteartion {count}");
        }
        finally {count++;}       
    }

private void ProcessCommand(string commandLineArguments)
{

    // Your command processing logic here

    MessageBox.Show(commandLineArguments);
    //...
    MessageBox.Show($"Leaving ProcessCommand {DateTime.Now});
}

相关问题