C# 如何在 WCF 回调上使用具有 APM-TAP 模式的完成端口执行异步 I/O

本文关键字:执行 异步 模式 APM-TAP WCF 回调 | 更新日期: 2023-09-27 18:32:34

我正在尝试使用双工协定中的WCF回调来利用I/O完成端口。我使用以下简单行来执行此操作:

OperationContext.Current.OnPushData(data);

其中 OnPushData 是在客户端实现的回调合约操作。
由于此行使用某些网络接口表示响应(输出操作(,并且 WCF 还依赖于可用作工作线程或 I/O CompletionPortThread 的 ThreadPool 线程,因此最好通过使用 TAP 或 APM 写入完成端口来利用 I/O CompletionPortThreads 模式(正如我提到的文章所建议的那样(而不是使用普通的工作线程,这将大大提高性能。

C# 如何在 WCF 回调上使用具有 APM-TAP 模式的完成端口执行异步 I/O

简短回答:
能够将异步 I/O 与双工 WCF 协定一起使用的技巧是以下简单代码:

    [OperationContract(IsOneWay = true)]
    Task OnPushData(data);

只需将回调合约方法的返回类型更改为 Task。 但这还不够,您需要实现如下异步方法

    public async Task PublishData()
    {
        communicationCallback = (ICommunicationObject)service.Callback;
        if (communicationCallback.State == CommunicationState.Opened)
        {
                await service.Callback.OnPushData(data);
        }
    }

仅此而已。这实际上提高了我的应用程序的性能。现在我能够看到调用 ThreadPool.GetAvailableThreads(workers,IO( 的 I/O 完成端口线程

一些说明:
据我了解,为了能够使用异步I/O机制,您需要执行以下操作:

1-确定您的I/O操作。
2-一种封装异步I/O逻辑的方法。
3-一种回调机制,将在异步I/O完成时调用,其目的主要是获取异步I/O的结果。
4-将保存异步I/O结果的对象。

.NET 框架提供了 3 种设计模式来做到这一点:

1- IAsyncResult

Asynchrnous Pattern:其中 BeginxxxEndxxx 将封装您的异步逻辑以及表示回调方法的回调委托,当然还有用于保存异步 I/O 结果的 IAsyncResult 对象。
2-基于任务的异步模式:仅使用一个类,即任务以及便于使用TAP模式的异步/等待关键字。
3-基于事件的异步模式。

有关如何将这些模式与 WCF 服务一起使用的详细信息,请参阅如何实现异步服务操作

但是,

上一个链接非常适合实现异步请求/响应服务,但是,没有关于如何使用回调合约执行此操作的说明。
不幸的是,就我而言,我必须使用 WCF 框架实现订阅者/发布者模式,其中数据发布由服务端定期(每 1 秒(启动。

更多详情:
我将尽量缩短
:WCF 依赖于 .NET Framework 提供的 ThreadPool。线程池有 2 种线程:
1-工作线程:用于计算绑定操作。
2- I/O 完成端口线程:用于获取 I/O 操作的结果。

必须区分 IOCP 线程和由 CLR 启动的 IOCP 对象。IOCP 线程角色是传递 I/O 操作的结果,而 IOCP 对象是由 CLR 启动的接收所有 I/O 请求的对象。换句话说,它们协作以实现 I/O 操作。

您需要知道的第一件事是,您发出的任何 I/O 请求都将导致系统调用,无论您使用的是同步还是异步范例,都将启动一个名为 IRP(I/O 请求数据包(的对象。

I/O 完成端口 (IOCP( 只不过是由 CLR 启动的类似队列的对象。此对象负责接收所有 I/O 已完成请求 (IRP(。在这一点上,这里有2种可能性:
1-您的I/O操作由同步方法调用:在这种情况下,调用方线程将被阻塞,直到I/O操作完成。
2-您的I/O操作由异步方法调用:在这种情况下,调用方线程将继续执行,并且在完成之前不会阻止I/O操作。

假设您使用的是异步方法,则异步 I/O 操作完成后,这意味着 IRP 对象将被处理,现在它将排队到 IOCP 对象。ThreadPool IOCP 线程将扮演从 IOCP 中提取相对 IRP 的角色,该 IRP 将包装在 APM 的 IAsyncResult或 TAP 的任务对象中,并通过回调机制将此对象传递到应用程序级别。

一些参考资料:

[1]: https://msdn.microsoft.com/en-us/library/ms734701.aspx
[2]: http://blog.stephencleary.com/2012/08/async-wcf-today-and-tomorrow.html
[3]: http://southworks.com/blog/2013/10/29/asynchronous-io-in-c-io-completion-ports/
[4]: http://southworks.com/blog/2013/08/02/asynchronous-io-in-c-introduction/
[5]: http://mikehadlow.blogspot.com/2011/03/7000-concurrent-connections-with.html
[6]: https://msdn.microsoft.com/en-US/library/MS731177(v=vs.110(.aspx
[7]: http://www.amazon.es/Clr-Via-C-Developer-Reference/dp/0735667454