首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >命名管道-异步窥视

命名管道-异步窥视
EN

Stack Overflow用户
提问于 2009-12-17 12:02:38
回答 2查看 4.4K关注 0票数 9

我需要找到一种方法,当以异步模式打开的System.IO.Pipe.NamedPipeServerStream上有更多可供读取的数据时,我需要得到通知- WaitHandle将是理想的。我不能简单地使用BeginRead()来获得这样的句柄,因为我可能会收到另一个想要写入管道的线程的信号-因此我必须释放管道上的锁并等待写入完成,而NamedPipeServerStream没有CancelAsync方法。我还尝试过调用BeginRead(),然后在线程收到信号时调用管道上的win32函数CancelIO,但我不认为这是一个理想的解决方案,因为如果在数据到达和处理时调用CancelIO,它将被删除-我仍然希望保留这些数据,但在写入之后的某个时间处理它。我怀疑win32函数PeekNamedPipe可能有用,但我希望避免使用它不断轮询新数据。

在likley事件中,上面的文本有点不清楚,这里大致是我希望能够做的事情……

代码语言:javascript
复制
NamedPipeServerStream pipe;
ManualResetEvent WriteFlag;
//initialise pipe
lock (pipe)
{
    //I wish this method existed
    WaitHandle NewDataHandle = pipe.GetDataAvailableWaithandle();
    Waithandle[] BreakConditions = new Waithandle[2];
    BreakConditions[0] = NewDataHandle;
    BreakConditions[1] = WriteFlag;
    int breakcode = WaitHandle.WaitAny(BreakConditions);
    switch (breakcode)
    {
        case 0:
            //do a read on the pipe
            break;
        case 1:
            //break so that we release the lock on the pipe
            break;
     }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-21 08:25:40

好了,我只是从我的代码中删除了这个,希望我删除了所有应用程序逻辑的东西。其思想是尝试使用ReadFile进行零长度读取,并在另一个线程想要写入管道时等待lpOverlapped.EventHandle (在读取完成时触发)和WaitHandle集。如果读操作由于写入线程而中断,请使用CancelIoEx取消零长度的读操作。

代码语言:javascript
复制
NativeOverlapped lpOverlapped;
ManualResetEvent DataReadyHandle = new ManualResetEvent(false);
lpOverlapped.InternalHigh = IntPtr.Zero;
lpOverlapped.InternalLow = IntPtr.Zero;
lpOverlapped.OffsetHigh = 0;
lpOverlapped.OffsetLow = 0;
lpOverlapped.EventHandle = DataReadyHandle.SafeWaitHandle.DangerousGetHandle();
IntPtr x = Marshal.AllocHGlobal(1); //for some reason, ReadFile doesnt like passing NULL in as a buffer
bool rval = ReadFile(SerialPipe.SafePipeHandle, x, 0, IntPtr.Zero,
   ref lpOverlapped);
int BreakCause;
if (!rval) //operation is completing asynchronously
{
   if (GetLastError() != 997) //ERROR_IO_PENDING, which is in fact good
      throw new IOException();
   //So, we have a list of conditions we are waiting for
   WaitHandle[] BreakConditions = new WaitHandle[3];
   //We might get some input to read from the serial port...
   BreakConditions[0] = DataReadyHandle;
    //we might get told to yield the lock so that CPU can write...
   BreakConditions[1] = WriteRequiredSignal;
   //or we might get told that this thread has become expendable
   BreakConditions[2] = ThreadKillSignal;
   BreakCause = WaitHandle.WaitAny(BreakConditions, timeout);
}
else //operation completed synchronously; there is data available
{
   BreakCause = 0; //jump into the reading code in the switch below
}
switch (BreakCause)
{
   case 0:
      //serial port input
      byte[] Buffer = new byte[AttemptReadSize];
      int BRead = SerialPipe.Read(Buffer, 0, AttemptReadSize);
      //do something with your bytes.
      break;
   case 1:
      //asked to yield
      //first kill that read operation
      CancelIoEx(SerialPipe.SafePipeHandle, ref lpOverlapped);
      //should hand over the pipe mutex and wait to be told to tkae it back
      System.Threading.Monitor.Exit(SerialPipeLock);
      WriteRequiredSignal.Reset();
      WriteCompleteSignal.WaitOne();
      WriteCompleteSignal.Reset();
      System.Threading.Monitor.Enter(SerialPipeLock);
      break;
   case 2:
      //asked to die
      //we are the ones responsible for cleaning up the pipe
      CancelIoEx(SerialPipe.SafePipeHandle, ref lpOverlapped);
      //finally block will clean up the pipe and the mutex
      return; //quit the thread
}
Marshal.FreeHGlobal(x);
票数 9
EN

Stack Overflow用户

发布于 2010-03-20 05:09:12

浏览MSDN,我看不到任何机制来做你想要的。最快的解决方案可能是使用互操作来访问PeekNamedPipe。如果不想使用interop,可以在自定义类中抽象管道,并在抽象中提供peek功能。抽象将处理所有的信号,并且必须协调对管道的读取和写入。显然,这不是一项微不足道的任务。

另一种选择,如果可能,在您的情况下,是考虑使用WCF,这是相当抽象的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1919373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档