BinaryFormatter.Deserialize 挂起整个线程

BinaryFormatter.Deserialize hangs the whole thread

我有两个通过命名管道连接的简单应用程序。在客户端,我有一种方法可以每 n 毫秒检查一次传入的消息:

private void timer_Elapsed(Object sender, ElapsedEventArgs e)
{
      IFormatter f = new BinaryFormatter();
      try
      {
           object temp = f.Deserialize(pipeClient); //hangs here
           result = (Func<T>)temp;
      }
      catch
      {
      }
}

一开始管道是空的,f.Deserialize 方法挂起了整个应用程序。而且我什至不能检查那个管道是空的?这个问题有解决办法吗?

更新: 试过 XmlSerializer,一切都一样。

挂在你身上的是pipeClient.Read(两个格式化程序在内部进行的调用。

当您调用 Read:

时,这是 Stream 的预期行为

Return Value
Type: System.Int32
The total number of bytes that are read into buffer. This might be less than the number of bytes requested if that number of bytes is not currently available, or 0 if the end of the stream is reached.

所以流将阻塞直到数据出现或抛出超时异常,如果它是支持超时的流类型。它永远不会只是 return 而不阅读任何东西,除非你是 "at the end of the stream",对于 PipeStream(或类似的 NetworkStream)只有在连接关闭时才会发生。

您解决问题的方法是不要使用计时器来检查是否有新消息到达,只需启动一个后台线程并让它处于循环中,它会阻塞自己直到消息出现。

class YourClass
{
    public YourClass(PipeStream pipeClient)
    {
        _pipeClient = pipeClient;
        var task = new Task(MessageHandler, TaskCreationOptions.LongRunning);
        task.Start();
    }

    //SNIP...

    private void MessageHandler()
    {
        while(_pipeClient.IsConnected)
        {
            IFormatter f = new BinaryFormatter();
            try
            {
                 object temp = f.Deserialize(_pipeClient);
                 result = (Func<T>)temp;
            }
            catch
            {
                //You really should do some kind of logging.
            }
        }
    }
}