BinaryFormatter.反序列化挂起整个线程
本文关键字:线程 挂起 反序列化 BinaryFormatter | 更新日期: 2023-09-27 17:53:34
我有两个通过命名管道连接的简单应用程序。在客户端,我有一个方法,每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方法挂起整个应用程序。我都不能检查水管有没有空吗?这个问题有什么解决办法吗?
UPD:尝试XmlSerializer,一切都是一样的
让你挂心的是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.
}
}
}
}