【问题标题】:Asynchronous Streaming in WCFWCF 中的异步流式处理
【发布时间】:2014-06-01 03:59:05
【问题描述】:

我正在使用 WCF 进行流式处理,我对 MSDN 关于 WCF 中的大数据和流式处理的文章中的“Enabling Asynchronous Streaming”段落的含义有疑问。

要启用异步流式传输,请添加 DispatcherSynchronizationBehavior 服务的端点行为 主机并将其AsynchronousSendEnabled 属性设置为true。我们有 还增加了发送时真正的异步流的能力 边。这提高了服务在以下场景中的可伸缩性 正在将消息流式传输到多个客户端,其中一些客户端运行缓慢 阅读可能是由于网络拥塞或根本不阅读。 在这些场景中,我们现在不会阻塞 每个客户的服务。这确保了服务能够处理 更多的客户端,从而提高服务的可扩展性。

我明白上面的意思是我加了

<behaviors>
  <endpointBehaviors>
    <behavior name="AsyncStreaming">
      <dispatcherSynchronization asynchronousSendEnabled="true" />
    </behavior>
  </endpointBehaviors>
  ...

到我的web.config 文件并在我的端点中引用AsyncStreaming 行为,但是我不明白这些步骤对我有什么作用。我是否需要修改我的代码才能利用这种异步性?

同样关于一个类似的主题(但如果它太不同我会将它移到一个新问题),如何在 WCF 中使用 Streams 使用 async/await 效果?我可以在我的服务合同中使用Task&lt;Stream&gt; Foo() 吗?我进行了一些数据库调用,最终将其结果包装到一个自定义流中,该流将从 WCF 服务返回。能够使用ExecuteDataReaderAsync() 之类的东西非常有用,在处理流式消息而不是缓冲消息时我还能使用它吗?

我已经对其进行了测试,并且我知道它使用任务“有效”,但我不知道这样做是否会导致函数回退到“缓冲”模式,就像您向函数提供多个参数时一样(请参阅在同一 MSDN 页面上的“Programming Model for Streamed Transfers”的第 3 段),我不知道如何检查是否发生这种情况。

【问题讨论】:

  • 嗨斯科特!我对任务包装的结果完全有同样的疑问。您能否确认它们的使用是否会导致通道恢复到“缓冲”模式?

标签: c# wcf asynchronous streaming async-await


【解决方案1】:

我通过 .NET 参考源将其追溯到 RequestContext。显然,ChannelHandler.sendAsynchronously 字段控制消息回复是异步完成(通过RequestContext.BeginReply/EndReply APM 方法)还是通过RequestContext.Reply 同步完成。

据我所知,所有这些都是释放返回到池中的服务器端线程,否则它将在RequestContext.Reply 内忙于将流“泵送”到客户端,只要因为Stream 对象在服务器上是活动的。

这似乎是完全透明的,所以我认为您可以安全地使用基于 TAP 的合约方法 async 并返回 Task&lt;Stream&gt;。例如,在另一种合同方法中,您可以使用await Stream.WriteAsync。

当你到达那里时,请分享你的实际经验作为你自己的答案,我会对细节非常感兴趣:)

【讨论】:

  • 我必须在运行时使用“await”语句来释放线程吗?
【解决方案2】:

关于复杂主题的好问题。我已经实现了一个流式 WCF 服务来容纳大量(高达 2GB)的下载,但是我也对这个 AsyncStreaming=True 业务感到有点困惑,因为 WCF 已经是异步的(因为每个连接的客户端都有自己的线程和异步请求和接收)只要

 <ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Multiple, InstanceContextMode:=InstanceContextMode.PerCall)>

但您必须更改代码才能使流式传输工作。即使您有 Binding.TransferMode = TransferMode.Streamed ,如果您不更改代码以便上传和下载功能 A)获取和返回流和 B)您的上传和下载函数实现如下:

//oBuffer is your content
if (oBuffer != null) {
    oStream = new MemoryStream(oBuffer);

    if (oStream.CanSeek) {
        oStream.Seek(0, SeekOrigin.Begin);
    }
    return oStream;
}

这是我用作指南的一篇不错的 HowTo 文章:http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP

【讨论】:

  • 对于您的第二部分,我的意思是我是否必须对我的代码进行任何更改才能从 asyncStreaming=false 变为 asyncStreaming=true,我并不是说要更改我的代码以支持 TransferMode.Streaming,这种变化是很久以前完成的。
  • 我没有使用 asyncStreaming=True 或 =False,但程序却是异步运行的。是的,您必须将 Transfermode 更改为 Streaming,但您还需要更改代码,以便返回 Stream 并且它可以搜索。这样做是允许客户端(必须以类似方式设置)请求流的下一部分。我花了一段时间才明白这一点,但将 WCF 流视为 File 对象。
  • 当你编写一个程序来读取一个大文件时,程序不会等到整个文件被读取后才将字节返回给程序。相反,它读取(一些)并输出到字节(即异步)。 WCF 的工作方式相同,这就是它对大数据传输有用的原因。它开始读取,但在读取所有字节之前,它已经将它拥有的字节发送到客户端。在客户端获得第一组字节后,客户端将联系主机(在幕后,您不必对其进行编程)以获取下一组字节。
  • 因此,客户端程序有效地接管了进程的控制权,请求更多字节,直到接收到所有数据。关注?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多