C#:异步NamedPipeServerStream管道正在关闭异常

2024-01-22

我之前关于同一主题的问题:C#:异步NamedPipeServerStream理解 https://stackoverflow.com/questions/11435262/c-asynchronous-namedpipeserverstream-understanding现在我有下一个:

private void StartListeningPipes()
{
    try
    {
        isPipeWorking = true;
                namedPipeServerStream = new NamedPipeServerStream(PIPENAME, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, BUFFERSIZE, BUFFERSIZE);
                Console.Write("Waiting for client connection...");
                while(isPipeWorking)
                {
            IAsyncResult asyncResult = namedPipeServerStream.BeginWaitForConnection(this.WaitForConnectionAsyncCallback, null);
                        Thread.Sleep(3*1000);
                }
        }
        //// Catch the IOException that is raised if the pipe is broken or disconnected.
        catch (IOException e)
        {
        Console.WriteLine("IOException: {0}. Restart pipe server...", e.Message);
                StopListeningPipes();
                StartListeningPipes();
        }
        //// Catch ObjectDisposedException if server was stopped. Then do nothing.
        catch (ObjectDisposedException)
        {
        }
}

private void WaitForConnectionAsyncCallback(IAsyncResult result)
{
    try
    {
        namedPipeServerStream.EndWaitForConnection(result);
        Console.WriteLine("Client connected.");
        namedPipeServerStream.WaitForPipeDrain();
                byte[] buff = new byte[BUFFERSIZE];
                namedPipeServerStream.Read(buff, 0, BUFFERSIZE);
                string recStr = TrimNulls(buff);
                Array.Clear(buff, 0, buff.Length);
                Console.WriteLine();
                Console.WriteLine("'"+recStr+"'");
    }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e.Message);            
        }
}

但我越来越

The pipe is being closed Exception每次我收到客户的消息

Why?

我的客户:

 using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(General.PIPENAME))
{
    try
        {
        byte[] bytes = General.Iso88591Encoding.GetBytes(sendingMessage);
                pipeStream.Write(bytes, 0, bytes.Length);
                pipeStream.Flush();
                pipeStream.WaitForPipeDrain();
        }
        catch (TimeoutException)
        {
        Console.WriteLine("Timeout error!");
        }
    catch (Exception e)
        {
        Console.WriteLine(string.Format("Error! ", e.Message));
        }
}

目前最终代码是:

/// <summary>
        /// Create new NamedPipeServerStream for listening to pipe client connection
        /// </summary>
        private void ListenForPipeClients()
        {
            if (!this.isListeningToClients)
                return;

            try
            {
                PipeSecurity ps = new PipeSecurity();
                PipeAccessRule par = new PipeAccessRule("Everyone", PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow);
                ps.AddAccessRule(par);
                pipeClientConnection = new NamedPipeServerStream(General.PIPENAME, PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, General.BUFFERSIZE, General.BUFFERSIZE, ps);
                Console.Write("Waiting for client connection...");
                /*namedPipeServerStream.WaitForConnection();
                OnPipeConnected(namedPipeServerStream);*/
                IAsyncResult result = pipeClientConnection.BeginWaitForConnection(OnPipeConnected, pipeClientConnection);
            }
            catch (ObjectDisposedException)
            {
                //// Catch ObjectDisposedException if server was stopped. Then do nothing.
            }
            catch (Exception e)
            {
                Console.WriteLine("Error occures: {0}. Restart pipe server...", e.Message);
                this.logger.Add(LogLevel.Warning, string.Format("Error occures: {0}. Restart pipe server...", e.Message));
                ListenForPipeClients();
            }
        }

        /// <summary>
        /// Async callback on client connected action
        /// </summary>
        /// <param name="asyncResult">Async result</param>
        private void OnPipeConnected(IAsyncResult asyncResult)
        {
            using (var conn = (NamedPipeServerStream)asyncResult.AsyncState)
            {
                try
                {
                    conn.EndWaitForConnection(asyncResult);
                    Console.WriteLine("Client connected.");
                    PipeClientConnection clientConnection = new PipeClientConnection(conn, notifierSenderCache, defaultStorageTime);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    this.logger.Add(LogLevel.Warning, e.Message);
                }
            }

            ListenForPipeClients();
        }

看来你需要一个单独的NamedPipeServerStream对于每个客户。 (请注意,我不是发现这一点的人,请参阅其他答案。)我想象工作服务器端看起来像这样(草稿代码):

while(this.isServerRunning)
{
     var pipeClientConnection = new NamedPipeServerStream(...);

     try
     {
         pipeClientConnection.WaitForConnection();
     }
     catch(...)
     {
         ...
         continue;
     }

     ThreadPool.QueueUserWorkItem(state =>
          {
               // we need a separate variable here, so as not to make the lambda capture the pipeClientConnection variable, which is not recommended in multi-threaded scenarios
               using(var pipeClientConn = (NamedPipeServerStream)state)
               {
                    // do stuff
                    ...
               }
          }, pipeClientConnection);
}

作为旁注,正如在对您的问题的评论中指出的那样,您通过调用每 3 秒启动一个新的异步调用来浪费内存BeginWaitForConnection在一个循环中(唯一不会浪费内存的情况是当新连接的间隔小于 3 秒时,但我怀疑您是否能确定这一点)。您会看到,基本上每 3 秒您就会启动一个新的异步调用,无论最后一个调用是否仍在挂起或已完成。此外,它再次没有考虑到您需要一个单独的NamedPipeServerStream对于每个客户。

要解决此问题,您需要消除循环,并使用回调方法“链接”BeginWaitForConnection 调用。这是使用 .NET 时在异步 I/O 中经常看到的类似模式。草稿代码:

private void StartListeningPipes()
{
    if(!this.isServerRunning)
    {
        return;
    }

    var pipeClientConnection = new NamedPipeServerStream(...);

    try
    {
        pipeClientConnection.BeginWaitForConnection(asyncResult =>
            {
                // note that the body of the lambda is not part of the outer try... catch block!
                using(var conn = (NamedPipeServerStream)asyncResult.AsyncState)
                {
                    try
                    {
                        conn.EndWaitForConnection(asyncResult);
                    }
                    catch(...)
                    {
                        ...
                    }

                    // we have a connection established, time to wait for new ones while this thread does its business with the client
                    // this may look like a recursive call, but it is not: remember, we're in a lambda expression
                    // if this bothers you, just export the lambda into a named private method, like you did in your question
                    StartListeningPipes();

                    // do business with the client
                    conn.WaitForPipeDrain();
                    ...
                }
            }, pipeClientConnection);
    }
    catch(...)
    {
        ...
    }
}

控制流程将是这样的:

  • 【主线程】StartListeningPipes():创建NamedPipeServerStream,发起BeginWaitForConnection()
  • [线程池线程 1] 客户端 #1 连接,BeginWaitForConnection() 回调:EndWaitForConnection() 然后 StartListeningPipes()
  • [线程池线程1] StartListeningPipes():创建新的NamedPipeServerStream,调用BeginWaitForConnection()
  • [线程池线程 1] 回到 BeginWaitForConnection() 回调:开始处理已连接的客户端 (#1)
  • [线程池线程 2] 客户端 #2 连接,BeginWaitForConnection() 回调:...
  • ...

我认为这比使用阻塞 I/O 困难得多 - 事实上,我不太确定我是否正确,如果您发现任何错误,请指出 - 而且它也更加令人困惑。

要在任一示例中暂停服务器,您显然需要设置this.isServerRunning标记为false.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#:异步NamedPipeServerStream管道正在关闭异常 的相关文章

随机推荐

  • 垃圾收集和毕加索的问题

    我正在尝试在 Google 地图标记的 InfoWindow 中设置 ImageView 并复制了代码这个答案 https stackoverflow com a 22043781非常准确 除了我的 InfoWindowAdapter 不是
  • 如何获取OSM节点或路径的城市和国家?

    我正在解析 OSM 数据的国家 地区摘录 我想要的是获取该点或方式所属的城市和国家的名称 这可能吗 我怎样才能获取这些信息 要检索此信息 您需要地理编码器 除非该节点具有相关的地址标签 https wiki openstreetmap or
  • R:如何对pairs()图中的对角线面板进行着色?

    以下代码将面板背景着色pairs情节在R 如何为对角线面板 打印变量名称的地方 着色 正如您所看到的 我尝试了它 但变量名称未正确对齐 无论出于何种原因 count lt 0 mypanel lt function x y count lt
  • 无法查询类型“y”上的字段“x”

    我需要 Graphql 查询方面的帮助 我正在尝试将投资组合网站部署到 Netlify 但在部署过程中出现此错误 我的代码可以在 localhost 上运行 但不能在 Netlify 上运行 我需要从 Contentful 中提取数据并用它
  • 获取标签 ID 以使用 GMAIL API 获取消息列表

    我正在使用 Google 几天前推出的新 GMAIL API v1 我想获取一些带有一些标签的电子邮件过滤列表 如果我想这样做 我需要得到label ID每个 label name 的但我只能得到所有标签的列表 任何想法 Diego 仅对于
  • Azure Blob 和队列线程安全

    我需要一些帮助来理解 azure CloudBlobClient CloudQueueClient 和 CloudBlob 类中的线程安全性 我正在开发一个辅助角色 其中包括多个独立的作业处理器 其中每个作业处理器从特定队列读取数据并写入
  • 如何向 Visual Studio 2010 添加 PHP 支持?

    我不喜欢分割我的开发环境 但我为同时使用 NET 系统和基于 Apache 的系统的客户构建项目 这意味着我被迫将时间分配在 Visual Studio for the NET 和 Dreamweaver 或其他 IDE 之间进行基于 PH
  • 从私有 Git 存储库推送/拉取的 Bash 脚本?

    我正在尝试找到一种方法 可以编写一个 bash 脚本 该脚本将在每天午夜自动从我们的私人 Github 存储库中提取并更新我们的开发站点 我们的仓库出于明显的原因是私有的 我发现的任何接近的东西总是要求输入密码 我们的服务器有自己的 Git
  • 在组件中加载 Google Maps JS API [Angular]

    如何加载外部js文件 来自 Angular 组件中的 url 具体来说 我正在尝试加载google maps api到我的角度项目 目前 我正在我的index html像这样 注意 我知道angular maps 那不是一个选择 您可以随时
  • 避免内存泄漏

    C 中如何使用重载运算符来防止内存泄漏 任何完整的例子 Regards PKV 如果您想避免内存泄漏 请不要使用delete 这可能看起来很矛盾 但事实是手动内存管理很容易出错 最好使用自动 或库 技术 在 C 中 对于您创建的每个对象 都
  • Haskell - 在“where”内定义带有守卫的函数

    我刚刚开始自学 Haskell 这段代码应该进行质因数分解 divides Integer gt Integer gt Bool divides small big big mod small 0 lowestDivisor Integer
  • Git 未推送所有文件和文件夹

    我正在尝试将整个目录推送到我的存储库中 每次我尝试这样做时 它只是推送自述文件 没有其他任何内容 正如您在第二张照片中看到的 那里只有 README 第三张图片是我的主目录的样子 第一张图是添加和推送的整个过程 向您展示我已经完成了必要的步
  • 如何在Java中使用AES加密数据

    我希望在java中使用AES cbc 加密一段数据 我想使用我自己的IV 我将其保存在字节数组中 并将我自己的密钥保存在字节数组中 我该怎么做呢 我正在搜索它以查找有关此主题的教程 This http www javamex com tut
  • SyntaxError:以 '\x82' 开头的非 UTF-8 代码 [重复]

    这个问题在这里已经有答案了 在处理 Python 字节 时 我在 Eclipse 中收到此错误 它说错误显示在两行中 source C My Documents C Code and zip command zip qr 0 1 forma
  • 我可以使用 HtmlAgilityPack 在某个标签上拆分 HTML 文档吗?

    例如 我有一堆 tr 我想收集的标签 我需要将每个标签拆分为单独的元素 以便于我更轻松地进行解析 这可能吗 标记的示例 tr class first in year td class year 2011 td td class img a
  • 更新时:自动更新日期/时间字段

    SQL Server 的更新字段上是否有相当于 MySQL 的功能 具有 DEFAULT CURRENT TIMESTAMP 和更新 CURRENT TIMESTAMP 子句 该列具有当前 其默认值的时间戳 以及 会自动更新 我正在寻找的是
  • 如何在android中以编程方式更改编辑文本的位置?

    我正在使用RelativeLayout 以编程方式创建多个彼此相邻的编辑文本 每个编辑文本的默认宽度是wrap content 但是当编辑文本到达屏幕边缘时 它会在视觉上改变其大小 那么当发生这种情况时我怎样才能让它移动到下一行呢 priv
  • R无法识别格式中的日期

    folk R 无法识别下一个日期类型 Jun 3 1986 我多次尝试将该列转换为因子或字符 stackoverflow 中的下一个示例不起作用并返回 NA sdate2 日期 我使用了小写字母 b 但它也不起作用 我的版本不太好用 as
  • mysql 选择每个月的记录数

    我需要在 mysql 中创建一个查询 该查询将返回 12 行 每个月一行 用于选择月份名称以及给定月份的记录数 我有两个表 months tbl 和 events tbl events tbl 中的每条记录都有一个 datetime 列和一
  • C#:异步NamedPipeServerStream管道正在关闭异常

    我之前关于同一主题的问题 C 异步NamedPipeServerStream理解 https stackoverflow com questions 11435262 c asynchronous namedpipeserverstream