BinaryFormatter.Deserialize挂起整个线程

时间:2015-06-04 21:14:53

标签: c# xmlserializer binaryformatter

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

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方法挂起整个应用程序。我甚至无法检查管道是否空了?有没有解决这个问题的方法?

UPD:尝试过XmlSerializer,一切都是一样的。

1 个答案:

答案 0 :(得分:0)

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

当您致电Read时,这是Stream的预期行为:

  

返回值
  输入:System.Int32
  读入缓冲区的总字节数。这可能小于字节数   请求当前可用的字节数,如果是,则为0   到达流的末尾。

因此,如果数据流是支持超时的流类型,则流将阻塞直到数据显示或抛出超时异常。它永远不会在没有读取任何内容的情况下返回,除非您“在流的末尾”,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.
            }
        }
    }
}