如何打开然后根据TPL Dataflow管道中的任务关闭连接?

时间:2014-03-18 16:56:24

标签: .net task-parallel-library tpl-dataflow

设置

我有一个处理许多类似任务的管道。它按顺序有三个段,A,然后是B,然后是C(每个段可能有多个阶段)。 A和C是机器的本地,B是远程的。

Three stage pipeline, middle stage B is remote

B部分中的任务,即远程部分,需要连接才能工作。他们应该共享一个连接。

问题

我想在第一个任务从A移动到B时创建连接,并在最后一个任务从B移动到C时关闭它。我该怎么办?

约束

如果它使解决方案更容易,我可以接受以下一个或多个约束:

  • B段只有一个阶段。
  • 一次只能处理B段中的一项任务。
  • 在A和B之间或B和C之间插入的队列(缓冲区)或任何其他块。

1 个答案:

答案 0 :(得分:3)

我就是这样做的:

  • 最初将某个connection变量设置为null
  • 每当处理一个项目时,如果需要,都会创建connection,然后再使用。
  • 块完成后(您可以使用Completed属性找到,假设您正确传播完成),Dispose()连接(如果已创建)。

在代码中,作为辅助方法,它看起来像这样:

public static TransformBlock<TInput, TOutput>
    CreateTransformBlockWithConnection<TInput, TOutput, TConnection>(
    Func<TInput, TConnection, TOutput> transform,
    Func<TConnection> connectionFactory)
    where TConnection : class, IDisposable
{
    TConnection connection = null;

    var block = new TransformBlock<TInput, TOutput>(
        input =>
        {
            if (connection == null)
                connection = connectionFactory();

            return transform(input, connection);
        });

    block.Completion.ContinueWith(
        _ =>
        {
            if (connection != null)
                connection.Dispose();
        });

    return block;
}

(请注意,如果connectionFactory返回null,这将无法正常运行。如果您对此感到担心,可以添加支票。)

用法示例(这会将每个字符串输入作为SQL命令执行并返回结果):

var block = CreateTransformBlockWithConnection(
    (string input, SqlConnection connection) =>
        new SqlCommand(input, connection).ExecuteScalar(),
    () => new SqlConnection());