C# 命名管道获取要读取的字节数

标签 c# named-pipes

我正在用 C# 开发一个简单的软件,它从命名管道(客户端)读取字节并将其转发到串行端口(对数据进行一些处理),反之亦然。它看起来像:

if(data available on the named pipe)
   write on com port (the data read from the named pipe) 
if(data available on the com port)
   write on named pipe (the data read from the com port)
repeat endlessly

问题是,如果没有数据可读取,则从命名管道读取数据会被阻止,直到有数据到来为止。因此另一端通信(com 端口到管道)也被阻止。

我尝试在它自己的线程中运行双向通信,但是当在另一个线程上执行读取操作(或等待数据)时,管道上的写入操作被阻止。 我尝试停止被阻止的线程并取消读取操作,但没有成功。

处理此类事情的最简单方法是:

  • 获取管道上可读取的字节数,如果为 0 则跳过读取

  • 或者读取操作超时,因此写入可能会在超时后发生(在此应用程序中,计时并不那么重要)。

这对于 com 端口部分非常有用,因为 comPort.BytesToRead 变量包含读取缓冲区中存在的字节数。

命名管道是一个客户端(由另一个软件创建的服务器),但如果更方便的话也可以是一个服务器。

有什么想法吗?!? 预先感谢您!

最佳答案

I have tried running both direction communication in it's own thread, but the write operation on the pipe is blocked while a read operation is performed (or waiting for data) on the other thread

只要使用正确的选项,管道可以同时用于读取和写入。这是一个玩具示例,演示了客户端和服务器在执行操作的顺序上存在分歧,但它正常工作:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.IO.Pipes;
using System.Text;
using System.Threading;

public class Bob
{
  static void Main()
  {
    var svr = new NamedPipeServerStream("boris", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte);
    var helper = Task.Run(() =>
    {
      var clt = new NamedPipeClientStream("localhost", "boris", PipeDirection.InOut, PipeOptions.Asynchronous);
      clt.Connect();
      var inBuff = new byte[256];
      var read = clt.ReadAsync(inBuff, 0, inBuff.Length);
      var msg = Encoding.UTF8.GetBytes("Hello!");
      var write = clt.WriteAsync(msg, 0, msg.Length);
      Task.WaitAll(read, write);
      var cltMsg = Encoding.UTF8.GetString(inBuff, 0, read.Result);
      Console.WriteLine("Client got message: {0}", cltMsg);
    });
    svr.WaitForConnection();
    var srvBuff = new byte[256];
    var srvL = svr.Read(srvBuff, 0, srvBuff.Length);
    var svrMsg = Encoding.UTF8.GetString(srvBuff, 0, srvL);
    Console.WriteLine("Server got message: {0}", svrMsg);
    var response = Encoding.UTF8.GetBytes("We're done now");
    svr.Write(response, 0, response.Length);
    helper.Wait();
    Console.WriteLine("It's all over");
    Console.ReadLine();
  }
}

(在实际使用中,我们会使用一些async方法来启动读写“线程”,而不是手动管理线程或任务)

关于C# 命名管道获取要读取的字节数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49315574/

相关文章:

c# - 什么是命名管道 (net.pipe) 限制?

c# - C# 服务器和 C++ 客户端之间的命名管道通信

PowerShell 命名管道 : no connection?

named-pipes - 命名管道类似于 "mkfifo"创建,但双向

C# 相当于 JavaScript "OR assignment"

c# - 如何在自定义 FrameworkElement 上设置指针事件样式

c# - Net 6 多个连接字符串

python-3.x - 如何停止在 Python 中的命名管道上阻塞的线程?

c# - 当我的鼠标指向 C# 中的按钮时,我想禁用其他按钮

c# - 如何暂停在工作线程上运行的任务并等待用户输入?