我们有一个WEPAPI服务,该服务使用消息处理程序以压缩形式将数据写入客户端。由于我们偶尔会收到非常大的消息,因此可以使用
配置系统HttpSelfHostConfiguration.TransferMode = TransferMode.Streamed;
压缩逻辑是:
public class CompressedHttpContent : CompressionHttpContent
{
public CompressedHttpContent(HttpContent content, ICompressor compressor)
: base(content, compressor)
{
}
protected async override Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context)
{
try
{
if (this.OriginalContent != null)
using (OriginalContent)
{
using (var contentStream = await OriginalContent.ReadAsStreamAsync())
{
var compressedStream = Compressor.CreateCompressionStream(stream);
await contentStream.CopyToAsync(compressedStream);
compressedStream.Close();
compressedStream.Dispose();
}
}
}
catch (Exception e)
{
...
throw;
}
}
}
[偶尔我们会收到类似的异常:
System.InvalidOperationException: The AsyncEventArgs implementation 'System.ServiceModel.Channels.BufferedOutputAsyncStream+WriteAsyncState' tried to set the state to Pending multiple times without completing a pending operation. This could be caused by an incorrect application AsyncEventArgs implementation or other extensibility code that invokes Set() multiple times.
Server stack trace:
at System.Runtime.AsyncEventArgs.set_State(OperationState value)
at System.Runtime.AsyncEventArgs.SetAsyncState(AsyncEventArgsCallback callback, Object state)
at System.Runtime.AsyncEventArgs`1.Set(AsyncEventArgsCallback callback, TArgument arguments, Object state)
at System.ServiceModel.Channels.BufferedOutputAsyncStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state)
at System.IO.Compression.DeflateStream.WriteDeflaterOutput(Boolean isAsync)
at System.IO.Compression.DeflateStream.InternalWrite(Byte[] array, Int32 offset, Int32 count, Boolean isAsync)
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
Exception rethrown at [0]:
at System.IO.Compression.DeflateStream.EndWrite(IAsyncResult asyncResult)
at System.IO.Compression.GZipStream.EndWrite(IAsyncResult asyncResult)
at System.IO.Stream.<>c.<BeginEndWriteAsync>b__53_1(Stream stream, IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.IO.Stream.<CopyToAsyncInternal>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at CompressedHttpContent.<SerializeToStreamAsync>d__2.MoveNext()
不幸的是,当我搜索此错误时,没有得到任何点击。
当我们使用缓冲传输模式时,我们没有得到这个。我们可能会更改为StreamedRequest模式,因为只有传入的请求可能非常大。
有人见过这个或有什么想法吗?
谢谢。
GZipStream似乎没有满足此要求,可以通过一些简单的代码进行测试(通常会引发异常)。
byte[] ba = File.ReadAllBytes(@"largerfile");
GZipStream gzs = new GZipStream(new MemoryStream(), CompressionLevel.Optimal);
gzs.WriteAsync(ba,0, 200000);
gzs.WriteAsync(ba, 0, 200000);
[我怀疑ASP.NET WebAPI可能以不受支持的方式调用GZipStream-尽管我尚不确信这实际上是正在发生的事情。