65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 VB.NET 的异步命名管道 (Overlapped IO)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (9投票s)

2006年12月6日

3分钟阅读

viewsIcon

103794

downloadIcon

4680

一篇文章,讲述了如何创建一个利用原生 Win32 重叠 IO 进行异步命名管道通信的库。

Sample Image

引言

本文展示了利用 Windows 重叠 API 进行通过命名管道的异步通信的要点。 与其他类似的代码相比,这段代码最大的成就在于服务器和客户端在您告诉它们时会真正地停止

背景

当我在尝试设置 Windows 服务和多个应用程序实例(每个用户一个实例)之间的进程间通信时,我偶然发现了各种文章,描述了如何使用命名管道来实现这一点。 这个想法似乎很有希望,但我下载和尝试的所有示例代码都有相同的弱点:服务器循环(在不同的线程上运行)在等待客户端连接时被锁定。 可以用来使服务器停止的唯一方法是

  1. Thread.Abort

    我认为这是一个非常丑陋的解决方案,因为你无法以此方式清理线程。

  2. 让客户端连接到服务器

    该服务可以连接到它自己 (!) 以解锁服务器线程。 这种方法不是很准确,并且喊着“解决方法”! 我阅读的一篇文章似乎有正确的角度来解决这个问题,并且在 CodeProject 的 这里,但是... 哎呀! 它是用 C++ 写的 :(。

重叠 IO

您只需要在 CreateNamedPipe (服务器端) 和 CreateFile (客户端) API 中指定 FILE_FLAG_OVERLAPPED 标志。 从那时起,一切都变得非常容易,因为您可以将 ManualResetEvent 的句柄传递给 OS (在 NativeOverlapped 结构中),它会在您的异步操作完成后向您发出信号。 这适用于所有在签名中具有 lpOverlapped 参数的 IO 函数。 因此,ConnectNamedPipe (服务器端) 变得真正异步,但 ReadFileWriteFile 函数也是如此。

System.IO.FileStream

在这里提到这个类似乎很奇怪,但如果有人检查命名管道上的示例代码,他会看到它们与普通文件的不同之处仅在于它们的创建方式(在服务器端),而您获得的句柄本质上是一个文件句柄! 那么为什么不使用现有的 FileStream 类进行 IO 操作呢? 接收文件句柄的构造函数在这里非常方便!

使用代码

我模仿 (或至少试图) PipeListennerPipeClient 之后的 TCPListenerTCPClient 类,因此它们的使用非常简单

PipeListenner (管道监听器)

Dim WithEvents Listenner As New _
    NamedPipes.PipeListener("myPipe")
Listenner.StartListenning

Private Sub Listenner_ClientConnected(ByVal sender As Object, _
        ByVal e As NamedPipes.ClientConnectedEventArgs) _
        Handles P.ClientConnected
    e.ClientStream.Read
    e.CleintStream.Write
    ...
End Sub

PipeClient

Dim Client As New NamedPipes.PipeClient("\\.\pipe\myPipe")
Client.Connect
Client.ClientStream.Read
Client.ClientStream.Write
    ...

前面的“代码”非常简单地演示了如何使用这些类。 对于更高级的实现(包括多线程操作),请下载演示应用程序源代码并查看内部内容。

关注点

正如前面提到的 Rob Manders 的文章 解释的那样,所有“魔力”都在这行代码中

Select Case Threading.WaitHandle.WaitAny(mSyncEvents, -1, False)

这部分代码的特殊之处在于它不工作... 至少,并非总是如此! 当应用程序在 Visual Studio 的“保护伞”下执行时,它似乎运行良好 99%,但如果您直接运行可执行文件,它会在客户端连接后立即崩溃。

另一种选择是

Select Case NativeMethods.WaitForMultipleObjects(mSyncEvents.Length, _
            mSyncEvents, False, UInteger.MaxValue)

但它总是会在 Visual Studio 下运行时失败,但在许多构建后运行发布的可执行文件时会起作用。 我真的希望这仅仅是由于我的电脑最近不在最佳状态造成的,因为我真的找不到任何解释! 也许一些阅读这篇文章的人能够提供关于这里可能发生的事情的线索!

© . All rights reserved.