[英]C# Cancel a list of tasks which are executing long running sql queries
等待時間到期后,我需要取消正在運行SQL查詢的任務列表。 我可以實現CancellationToken來取消任務。 但是取消是合作的,因此這意味着我必須在每一步之前檢查動作內部的取消令牌狀態。 但是在我的情況下,sql查詢是花費很長時間的查詢,並且我只能在查詢執行之前或之后檢查cancel令牌狀態。 在后一種情況下,它是無用的,那么如何根據取消令牌狀態在這些任務中取消查詢執行?
public void EnqueueTask(Action action, CancellationToken cancelToken = default(CancellationToken))
{
var task = new Task(action, cancelToken, TaskCreationOptions.LongRunning);
if (_workTaskQueue.TryAdd(task))
{
TaskHandler?.Invoke
(new TaskProcessingArguments
{
ISTaskAdded = true,
Message = "Task Added to Queue",
PendingTaskCount = _workTaskQueue.Count,
});
}
else
{
TaskHandler?.Invoke
(new TaskProcessingArguments
{
ISTaskAdded = false,
Message = "Timedout while adding Task to Queue",
PendingTaskCount = _workTaskQueue.Count,
});
}
}
public void DequeueTask(int maxConcurrency, CancellationToken ct)
{
var tasks = new List<Task>();
using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
{
foreach (var task in _workTaskQueue.GetConsumingEnumerable())
{
try
{
if (!(task.IsCanceled) && task.Status == TaskStatus.Created)
{
tasks.Add(task);
task.Start();
}
}
finally {
concurrencySemaphore.Release();
}
}
}
Task.WaitAll(tasks.ToArray());
}
void StartWorker()
{
Task.Factory.StartNew(() =>
{
try
{
taskQueue.DequeueTask(maxConcurrency, cancellationToken);
}
finally {
lock (syncObj)
{
IsCompleted = true;
}
//Logger.Info("Closing Worker task!!!");
}
}, TaskCreationOptions.LongRunning);
}
您需要在作為Action實例傳遞給EnqueueTask方法的函數中使用CancellationToken 。
例如,以下代碼顯示了如何將CancellationToken用於終止SQL命令的執行:
using (SqlConnection conn = new SqlConnection(sqlConnection))
{
conn.Open();
var cmd = conn.CreateCommand();
using (cancellationToken.Register(() => cmd.Cancel()))
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
編寫一個使用新線程啟動查詢的任務,該任務可以繼續檢查CancellationToken的狀態,並在需要時終止該線程。
您可以擴展Task <>並添加此功能,例如。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.