c# - 在 WCF 中使用任务构建异步操作契约(Contract)的正确方法

标签 c# .net multithreading wcf asynchronous

我正在构建一个 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 启动之前进行流复制,但这看起来不干净,实际上并不能解决我的困惑。

我的第二个问题是,如果我在操作合约中使用 Task,我应该保持操作合约的签名同步还是异步?如果我将操作契约(Contract)更改为:

[OperationContract(IsOneWay = true)]
[WebInvoke(Method = "POST", UriTemplate = "UploadData", BodyStyle = WebMessageBodyStyle.Bare)]
Task UploadDataAsync(Stream stream);

最佳答案

首先:您不需要Stream incomingStream = stream;

我有一个相同的服务,起初我像你一样实现它。我向您保证,在复制或完成任何类型的过程之前,WCF 不会处理流。但还有另一个问题。您可能会遇到线程外异常。(您可以阅读有关 Task.Run here 的更多信息。)。所以我让我的服务同步,但我称之为异步。这样我就可以达到最大的性能。

关于c# - 在 WCF 中使用任务构建异步操作契约(Contract)的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44014824/

相关文章:

c++ - 对象级 CSingleLock 与方法级 CSingleLock

c# - 动态(以编程方式)添加复选框和 checkedchanged 事件

c# - "ref int m_a"如何让包含m a的对象不被GC回收?

.net - 在 DataGrid 中显示二维数组

java - 具有同一可运行类的不同对象的多个线程可以重叠

c - 信号量队列

c# - 无法复制文件,即使在 C# 中授予了 FileIOPermission

c# - Windows Phone Company Hub 应用程序 - 无法覆盖/更新现有应用程序

php - PHP如何用作.NET语言(具体是ASP.NET)?

c# - 如何在 HTTPS 中处理自定义证书?