TPL Producer使用者模式 - 可能不会在已启动的任务上调用Start

时间:2017-08-10 19:14:20

标签: c# asp.net .net sql-server task-parallel-library

我正在尝试使用自定义sql clr代码在sql server中实现并行处理,如下面链接中的示例。

http://www.sqlnotes.info/2015/12/03/run-t-sql-in-parallel/

上述链接中的示例的问题是它使用线程和锁,并且耗费了大量时间。因此,在许多情况下,并行处理的收益可以忽略不计。所以为了解决这个问题,我试图创建一个类似的实用程序,它使用TPL使用Producer-Consumer模式。

生产者 - 是调用代码执行sql命令的sql procs。 使用者 - 该实用程序应该并行处理这些查询。

我将使用begin transaction,commit和sp_getapplock分批发送要处理的查询。消费者应该从头开始并继续寻找要处理的新任务,并在提交事务时结束。为此,我试图使用下面的代码:

List<Task> PendingTaskList = new List<Task>();

    void StartWorker()
    {
        (Task.Factory.StartNew(() =>
        {
            while (!IsClosed)
            {
                Parallel.ForEach(PendingTaskList, new ParallelOptions { MaxDegreeOfParallelism = 10 }, task =>
                {
                    if (task.Status == TaskStatus.Created)
                    {
                        task.Start();
                    }
                });
                while ((!IsClosed) && (PendingTaskList.Count == 0)) Task.Delay(1);
            }
        }, TaskCreationOptions.LongRunning)).Start();
    }


    void Enqueue(string commandText, SqlParameter[] paramList, string queryName, string attributeSysCode)
    {
        //TODO: Localize variables in here ...
        //TODO: Do parameter checking on the T-SQL command text paased here ...
        //TODO: Consider caching pre-compiled versions of popular T-SQL parameters by hashvalue of param string here as key ...

        SqlCommand cmd = new SqlCommand();
        cmd.CommandText = commandText;
        cmd.CommandTimeout = 0;
        cmd.CommandType = CommandType.Text;

        AsyncTaskItem item = new AsyncTaskItem() { Command = cmd, sqlParamList = paramList, QueryName = queryName, AttributeSysCode = attributeSysCode };
        var task = new Task(() => RunOne(item));
        PendingTaskList.Add(task.ContinueWith(t =>
            {
                PendingTaskList.Remove(t);
                CompletedTaskList.Add(t);
            }));

    }

上面的代码抛出错误&#34;可能无法在已经启动的任务上调用Start。&#39;&#34;

如何解决此问题?

1 个答案:

答案 0 :(得分:0)

取消对Start()的通话。由于StartNew()启动了它创建的任务,因此不需要Start()