我们正在使用 WCF 构建一个简单的 Web 服务,我们的产品使用该服务通过 WAN 链接上传大文件。它应该是一个简单的 HTTP PUT,并且在大多数情况下运行良好。
这是服务契约(Contract)的简化版本:
[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()
,根据 Reflector 分配了一个 Byte[]
缓冲区并继续从流中读取,直到它处于 EOF。换句话说,
Close
call 在返回之前从流中读取整个 100GB 的测试数据!现在可能不需要打电话
Close()
在这个流上。如果是这种情况,我想解释一下原因。但更重要的是,如果有人能向我解释为什么Close()
,我将不胜感激。行为方式,为什么它不被视为错误,以及如何重新配置 WCF 以免发生这种情况。
最佳答案
.Close()
旨在成为停止操作的“安全”和“友好”方式 - 它确实会在关闭之前完成当前正在运行的请求 - 按照设计。
如果你想扔掉大锤,用.Abort()
而是在您的客户端代理(或服务主机)上。这只是在不检查的情况下关闭所有内容,并且不喜欢等待操作完成。
关于wcf - 为什么 WCF 在 Close() 上读取输入流到 EOF?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1676563/