绕过TPL DataFlow

时间:2016-10-02 23:23:57

标签: c# wcf task-parallel-library simple-injector tpl-dataflow

我有一个Windows服务(使用Topshelf),它托管WCF服务(使用SimpleInjectorServiceHost创建)并且还旋转线程(使用Task.Run)。

这个想法是:

  • WCF服务接收命令
  • 将这些命令发布到BufferBlock<T>。该服务需要将BufferBlock<T>注入其构造函数
  • 线程应该是TransformBlock<T>,它将执行必要的操作并返回结果
  • 此结果需要通过WCF服务方法回读并返回给调用者

我刚开始使用TPL Dataflow,所以也许我对动作块的理解是完全错误的

我在Windows服务OnStart方法中旋转线程

for(var i = 0, i < Environment.ProcessorCount, ++i)
{
    Task.Run(() =>
    {
        using (var scope = Bootstrapper.BeginScope())
        {
            var threadHost = Bootstrapper.GetInstance<IThreadHost>();
            threadHost.DoWork(_cancellationTokenSource.Token);
        }
    }, _cancellationTokenSource.Token);
};

Bootstrapper.BeginScope简单地抽象出SimpleInjector的_container.BeginLifetimeScope()方法

IThreadHost / ThreadHost是一个简单的接口/类,它包含每种命令类型的方法。 DoWork应该等待BufferBlock并处理每个项目一次。

使用

启动WCF服务
if (_serviceHost != null)
{
    _serviceHost.Close();
}
_serviceHost = Bootstrapper.CreateServiceHost(typeof(NodeService));
_serviceHost.Open();

Bootstrapper.CreateServiceHost只是抽象出new SimpleInjectorServiceHost(_container, serviceType)

问:BufferBlock<T>是否应该是SimpleInjector注册的单身人士?

问:如何将每个DoWork的{​​{1}}设置为threadHost并链接到TransformBlock<T>

问:如何在BufferBlock<T>服务方法中获得TransformBlock<T>的输出? WCF服务方法将命令写入WCF,然后需要以某种方式等待输出?

1 个答案:

答案 0 :(得分:2)

我觉得你有点过于复杂了。您真的不需要TransformBlock工作者的线程 - TPL DataFlow中的每个块都已经有相应的任务。如果您愿意,可以optimize it's usage for your needs with options

您在解决方案中获得的是一般Producer/Consumer pattern,使用TPL DataFlow可以更轻松地完成。所以你的第一个问题的答案是:

  

问:BufferBlock应该是在SimpleInjector注册的单身人士吗?

是的,BufferBlockTransformBlock应该是单身,但这取决于第三个问题的答案

正如我已经说过的那样,你真的不需要TPLTPL DataFlow的帖子,所以第二个问题也很容易回答:

  

问:如何将每个threadHost的DoWork设置为TransformBlock和链接   到BufferBlock?

您应该在解决方案中不使用任何主题,并直接将TransformBlock链接到BufferBlock

至于第三个问题,这是有趣的部分,因为答案是:

  

问:如何在WCF服务方法中获得TransformBlock的输出?   WCF服务方法将命令写入BufferBlock然后需要   以某种方式等待输出?

取决于。

使用TPL DataFlow进行数据处理的主要思想是它是异步的,你无法确定退出TransformBlock时所拥有的是你的请求的结果 - 可能是使用其他请求转换的其他数据,只需使用OutputAvailableAsync()轮询输出,对于您的解决方案来说可能效率很低。

在这种情况下,您应该创建某种字典来处理结果,这样您就可以轻松获取信息,是否完成了请求。在这种实现的情况下,您可以返回请求的id,并引入另一种服务方法来获取该id的结果。

另一种方法是将数据流封装到一个帮助程序类中,该辅助程序类将包含它自己的BufferBlockTransformBlock副本,在这种情况下,您可以创建async使用轮询的方法,如链接示例中所示。请注意,在这种实施情况下,您根本不需要TPL DataFlow。