Необходимо закрыть метод Stream of WebInvoke
У меня есть служебный интерфейс с методом, который имеет параметр типа Stream
. Должен ли я закрывать поток после того, как я прочитал все данные из этого потока или это выполняется с помощью выполнения WCF Runtime, когда вызов метода завершен?
В большинстве примеров, которые я видел, читайте только данные из потока, но не вызывайте 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>
Ответы
Ответ 1
Свойство, которое контролирует поведение закрытия или не закрывает параметр, является свойством OperationBehaviorAttribute.AutoDisposeParameters
и может использоваться для отклонения от поведения по умолчанию true в отношении параметра Stream
, который закрывается после выхода из метода. Именно по этой причине вы не часто видите явное закрытие параметра. Если вы хотите переопределить поведение по умолчанию, вы можете принять явный контроль и закрыть поток после завершения операции с помощью OperationCompleted.
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
и, следовательно, вы несете ответственность за ее закрытие.