[英]how to cancel Task quicker
我有一個Windows服務,它啟動時啟動任務
這個任務有一個while循環,在執行一次迭代后,它會進入睡眠狀態5分鍾。
當我停止服務時,首先取消任務,然后執行其他一些操作
如果任務處於睡眠狀態,只有在它被喚醒時它才被取消,我希望它被取消,即使它正在睡覺而且不想等待它被喚醒。
以下是代碼
Task controllerTask = Task.Factory.StartNew(() =>
{
var interval = 300;
while(true)
{
if (cancellationToken.IsCancellationRequested)
break;
Thread.Sleep(interval * 1000);
if (cancellationToken.IsCancellationRequested)
break;
//SOME WORK HERE
}
}, cancellationToken);
有什么辦法嗎?
編輯:我無法使用Task.Delay,我在System.Threading.Tasks.Task命名空間中找不到它,因為我使用的是.Net Framework 4.0而不是4.5
有沒有其他更好的解決方案適用於4.0。
使用Task.Delay
而不是Thread.Sleep
。 它需要一個CancellationToken
參數,因此您可以在延遲結束之前中止它。
如果您使用的是異步代碼,可以這樣寫:
await Task.Delay(duration, cancellationToken);
如果它是同步代碼,您可以等待任務:
Task.Delay(duration, cancellationToken).Wait();
受其他答案啟發,使用等待此問題的簡單示例:
public static class TaskExtension
{
/// <summary>
/// Call to highlight fact that you do not want to wait on this task.
///
/// This nicely removes resharper warnings without need for comments.
/// </summary>
/// <param name="task"></param>
public static void FireAndForget(this Task task)
{
}
}
internal class Program
{
private static void Main(string[] args)
{
var cancellationToken = new CancellationTokenSource();
TaskCode(cancellationToken.Token).FireAndForget();
Console.ReadLine();
cancellationToken.Cancel();
Console.WriteLine("End");
Console.ReadLine();
}
private static async Task TaskCode(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var interval = TimeSpan.FromSeconds(1);
await Task.Delay(interval, cancellationToken);
//SOME WORK HERE
Console.WriteLine("Tick");
}
}
}
這是一個可以在C#4.0,VS2010中使用的阻止解決方案。
cancellationToken.WaitHandle.WaitOne(TimeSpan.FromMinutes(5));
當您取消令牌源或超時(即所需的睡眠間隔)時,它將取消阻止。
我已經將長時間睡眠分成多個小睡眠,以下是修改后的代碼:
Task controllerTask = Task.Factory.StartNew(() =>
{
while(true)
{
if (cancellationToken.IsCancellationRequested) break;
var sleepTime = 10;
if (interval < sleepTime)
interval = sleepTime;
var iteration = (interval / sleepTime);
if ((interval % sleepTime) > 0)
iteration++;
bool cancel = false;
for (int i = 0; i < iteration; i++)
{
Thread.Sleep(sleepTime * 1000);
if (cancellationToken.IsCancellationRequested) { cancel = true; break; };
}
if (cancel) break;
//SOME WORK HERE
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.