23

我有一个服务接口,其方法的参数类型为Stream。我应该在从该流中读取所有数据后关闭该流,还是在方法调用完成时由 WCF 运行时完成?

我见过的大多数例子,只从流中读取数据,但不要在流上调用 Close 或 Dispose。

通常我会说我不必关闭流,因为该类不是流的所有者,但原因是为什么要问这个问题是我们目前正在调查我们系统中的一个问题,即一些 Android 客户端,使用 HTTP-Post 向此服务发送数据有时会打开未关闭的连接(使用netstat哪个列表 ESTABLISHED Tcp 连接进行分析)。

[ServiceContract]
public interface IStreamedService {
    [OperationContract]
    [WebInvoke]
    Stream PullMessage(Stream incomingStream);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)]
public class MyService : IStreamedService  {

  public System.IO.Stream PullMessage(System.IO.Stream incomingStream) {
       // using(incomingStream) {
       // Read data from stream
       // }

       Stream outgoingStream = // assigned by omitted code;
       return outgoingStream;
  }

服务/绑定的配置

<webHttpBinding>
  <binding name="WebHttpBindingConfiguration" 
           transferMode="Streamed"
           maxReceivedMessageSize="1048576"
           receiveTimeout="00:10:00" 
           sendTimeout="00:10:00"
           closeTimeout="00:10:00"/>
</webHttpBinding>
4

1 回答 1

2

控制关闭或不关闭参数行为的属性是OperationBehaviorAttribute.AutoDisposeParameters属性,可用于偏离默认行为 true 关于Stream参数退出方法后关闭的行为。这就是您不经常看到参数显式关闭的原因。如果您想覆盖默认行为,您可以通过OperationCompleted事件在操作完成后进行显式控制并关闭 Stream 。

public Stream GetFile(string path) {
   Sream fileStream = null;    

   try   
   {
      fileStream = File.OpenRead(path);
   }
   catch(Exception)
   {
      return null;
   }

   OperationContext clientContext = OperationContext.Current;
clientContext.OperationCompleted += new EventHandler(delegate(object sender, EventArgs args)
   {
      if (fileStream != null)
         fileStream.Dispose();
   });

       return fileStream;
}

请记住,您收到的是您自己的副本,而Stream不是对客户的引用Stream,因此您有责任关闭它。

于 2012-12-20T22:12:40.420 回答