我正在尝试使用自定义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;
如何解决此问题?
答案 0 :(得分:0)
取消对Start()
的通话。由于StartNew()
启动了它创建的任务,因此不需要Start()
。