具有读/写超时的命名管道IPC示例

5

我正在苦苦寻找一种最佳方法来实现具有强大超时管理的命名管道IPC。我不是指在建立连接时的超时,而是指在读/写流上的超时。

我找到的所有示例都没有超时实现。

是否有人能够给我提供一个可行的示例和/或指向展示此功能的示例?


你是想使用普通的命名管道还是考虑使用基于命名管道的WCF? - Adam Gritt
@AdamGritt:直接命名管道。 - user564548
1个回答

3
你可能需要使用NamedPipeClientStream.BeginReadNamedPipeClientStream.BeginWrite进行异步读写操作;然后使用定时器来检测在一段时间内未发送或接收到数据的情况。
每当发送或接收数据时,就会设置一个DateTime字段为DateTime.Now,并且每次执行定时器时都会检查该字段以确定是否发生超时。如果超时,则可以关闭NamedPipeClientStream,并捕获NamedPipeClientStream.EndReadNamedPipeClientStream.EndWrite引发的异常。
我暂时还没有准备好工作示例,但如果需要,我会准备一份。希望这能帮助您度过难关。
这是一些非常粗略的示例代码。还需要完成更多的工作,例如实现IDisposable并添加写入方法。这应该有助于说明这个想法,但最好将此代码用作模型,而不是直接使用它。我已经测试了该代码以查看是否读取。
//this is a very rough model of how to do it. a lot more would need to be implemented
//i'm assuming you plan to continuously read from it. i can think up another example if you're not
//also not thread safe
public class MyPipeClient
{
    NamedPipeClientStream PipeClient = new NamedPipeClientStream("testpipe1");
    Timer TimeoutTimer;
    DateTime LastRead;
    const int TimeoutSeconds = 120; //2 mins

    //will connect and start receiving
    public void Connect()
    {
        PipeClient.Connect();
        LastRead = DateTime.Now;

        TimeoutTimer = new Timer(TimeoutCheck, this, 0, 1000); //check every second

        Read(this);
    }

    public void Disconnect()
    {
        PipeClient.Close(); PipeClient = null;
        TimeoutTimer.Dispose(); TimeoutTimer = null;
    }

    static void Read(MyPipeClient client)
    {
        PipeState state = new PipeState(client);

        try
        {
            client.PipeClient.BeginRead(state.Buffer, 0, state.Buffer.Length, ReadCallback, state);
        }
        catch (InvalidOperationException) //disconnected/disposed
        {
            return;
        }
    }

    static void ReadCallback(IAsyncResult ar)
    {
        PipeState state = (PipeState)ar.AsyncState;
        MyPipeClient client = state.Client;

        client.LastRead = DateTime.Now;

        int bytesRead;

        try
        {
            bytesRead = client.PipeClient.EndRead(ar);
        }
        catch (IOException) //closed
        {
            return;
        }

        if (bytesRead > 0)
        {
            byte[] data = state.Buffer;

            //TODO: something
        }
        else //i've never used pipes, so i'm assuming this behavior exists with them
        {
            client.Disconnect();
            return;
        }

        Read(client);
    }

    static void TimeoutCheck(object state)
    {
        MyPipeClient client = (MyPipeClient)state;

        TimeSpan timeSinceLastRead = DateTime.Now - client.LastRead;

        if (timeSinceLastRead.TotalSeconds > TimeoutSeconds)
        {
            client.Disconnect();
        }
    }
}

class PipeState
{
    public byte[] Buffer = new byte[4096];
    public MyPipeClient Client;

    public PipeState(MyPipeClient client)
    {
        Client = client;
    }
}

很好的例子,我会尝试这个。 - user564548

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接