使用 WCF 中的任务构建异步操作合同的正确方法
Posted
技术标签:
【中文标题】使用 WCF 中的任务构建异步操作合同的正确方法【英文标题】:Correct way to build asynchronously operation contract using a Task in WCF 【发布时间】:2017-10-16 07:46:50 【问题描述】:我正在构建一个 WCF 服务,它接受来自 HTTP 客户端的大块数据(通常为 4MB)POST,操作契约是一个具有 Stream 类型参数的函数,如下所示:
[OperationContract(IsOneWay = true)]
[WebInvoke(Method = "POST", UriTemplate = "UploadData", BodyStyle = WebMessageBodyStyle.Bare)]
void UploadData(Stream stream);
由于 UploadData 将由 I/O 完成线程运行,并且我知道数据的处理可能需要一段时间,所以一般我应该尽快将其返回到 I/O 完成线程池,否则会影响并发性,所以我计划启动一个任务来将流复制到 MemoryStream 并从那里进行以下数据处理。 让我困惑的是,由于WCF创建并维护了流对象,Task.Run返回后,UploadData退出,WCF认为这个请求已经被服务,但实际上我只是开始将流复制到一个MemoryStream中,如何确保流对象仍然存在并且在复制完成之前没有被 WCF 释放?
public void UploadData(Stream stream)
Stream incomingStream = stream; // is variable capture necessary here?
Task.Run(() =>
using (MemoryStream memoryStream = new MemoryStream())
using (incomingStream)
stream.CopyTo(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
// process data
当然,我可以在 Task 开始之前进行流复制,但这看起来并不干净,实际上并不能回答我的困惑。
我的第二个问题是,如果我在操作合同中使用任务,我应该保持操作合同的签名同步还是异步?如果我将运营合同更改为:
[OperationContract(IsOneWay = true)]
[WebInvoke(Method = "POST", UriTemplate = "UploadData", BodyStyle = WebMessageBodyStyle.Bare)]
Task UploadDataAsync(Stream stream);
【问题讨论】:
【参考方案1】:起初:你不需要Stream incomingStream = stream;
。
我有相同的服务,起初我像你一样实施它。我向您保证,在复制或完成任何类型的过程之前,WCF 不会处理流。但还有另一个问题。你可能会得到线程外异常。(你可以阅读更多关于Task.Run
here的信息。)。所以我让我的服务同步,但我称之为异步。这样我就可以达到最大的性能。
【讨论】:
以上是关于使用 WCF 中的任务构建异步操作合同的正确方法的主要内容,如果未能解决你的问题,请参考以下文章