我们正在使用WCF构建一个简单的Web服务,我们的产品使用它通过WAN链接上载大型文件。它应该是一个简单的http-put,并且在大多数情况下都可以正常工作。
以下是服务合同的简化版本:
[ServiceContract, XmlSerializerFormat]
public interface IReplicationWebService
{
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "agents/{sourceName}/epoch/{guid}/{number}/{type}")]
ReplayResult PutEpochFile(string sourceName, string guid, string number, string type, Stream stream);
}
在执行本合同时,我们从
stream
把它写进一个文件。这很好,所以我们为没有足够的磁盘空间存储文件的情况添加了一些错误处理。大致如下:
public ReplayResult PutEpochFile(string sourceName, string guid, string number, string type, Stream inStream)
{
//Stuff snipped
try
{
//Read from the stream and write to the file
}
catch (IOException ioe)
{
//IOException may mean no disk space
try
{
inStream.Close();
}
// if instream caused the IOException, close may throw
catch
{
}
_logger.Debug(ioe.ToString());
throw new FaultException<IOException>(ioe, new FaultReason(ioe.Message), new FaultCode("IO"));
}
}
为了测试这个,我将向一个没有足够空间容纳该文件的服务器发送一个100GB文件。如预期的那样,这会引发一个异常,但调用
inStream.Close()
似乎挂了起来。我查过了,实际发生的是
Close()
穿过WCF管道直到到达
System.ServiceModel.Channels.DrainOnCloseStream.Close()
,根据反射镜分配
Byte[]
缓冲并一直从流中读取数据,直到到达EOF为止。
也就是说,
Close
调用正在从流中读取整个100GB的测试数据,然后返回!
现在可能我不需要打电话
关闭()
在这条小溪上。如果是这样的话,我想解释一下原因。但更重要的是,如果有人能向我解释为什么
关闭()
是这样的行为,为什么它不被认为是一个错误,以及如何重新配置WCF以避免这种情况发生。