Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 3

using System;

using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace IntroducingTasks
{
class CancelingTasks
{
static void Main(string[] args)
{
CancelableTasks();
MonitoringCancelation();
CompositeCancelationToken();

Console.WriteLine("Main program done, press any key.");


Console.ReadKey();
}

private static void WaitingForTimeToPass()


{
// we've already seen the classic Thread.Sleep

var cts = new CancellationTokenSource();


var token = cts.Token;
var t = new Task(() =>
{
Console.WriteLine("You have 5 seconds to disarm this bomb by pressing a
key");
bool canceled = token.WaitHandle.WaitOne(5000);
Console.WriteLine(canceled ? "Bomb disarmed." : "BOOM!!!!");
}, token);
t.Start();

// unlike sleep and waitone


// thread does not give up its turn
Thread.SpinWait(10000);
Console.WriteLine("Are you still here?");

Console.ReadKey();
cts.Cancel();
}

private static void CompositeCancelationToken()


{
// it's possible to create a 'composite' cancelation source that involves
several tokens
var planned = new CancellationTokenSource();
var preventative = new CancellationTokenSource();
var emergency = new CancellationTokenSource();

// make a token source that is linked on their tokens


var paranoid = CancellationTokenSource.CreateLinkedTokenSource(
planned.Token, preventative.Token, emergency.Token);

Task.Factory.StartNew(() =>
{
int i = 0;
while (true)
{
paranoid.Token.ThrowIfCancellationRequested();
Console.Write($"{i++}\t");
Thread.Sleep(100);
}
}, paranoid.Token);

paranoid.Token.Register(() => Console.WriteLine("Cancelation requested"));

Console.ReadKey();

// use any of the aforementioned token soures


emergency.Cancel();
}

private static void MonitoringCancelation()


{
var cts = new CancellationTokenSource();
var token = cts.Token;

// register a delegate to fire


token.Register(() =>
{
Console.WriteLine("Cancelation has been requested.");
});

Task t = new Task(() =>


{
int i = 0;
while (true)
{
if (token.IsCancellationRequested) // 1. Soft exit
// RanToCompletion
{
break;
}
else
{
Console.Write($"{i++}\t");
Thread.Sleep(100);
}
}
});
t.Start();

// canceling multiple tasks


Task t2 = Task.Factory.StartNew(() =>
{
char c = 'a';
while (true)
{
// alternative to what's below
token.ThrowIfCancellationRequested(); // 2. Hard exit, Canceled

if (token.IsCancellationRequested) // same as above, start HERE


{
// release resources, if any
throw new OperationCanceledException("No longer interested in printing
letters.");
}
else
{
Console.Write($"{c++}\t");
Thread.Sleep(200);
}
}
}, token); // don't do token, show R# magic

// cancellation on a wait handle


Task.Factory.StartNew(() =>
{
token.WaitHandle.WaitOne();
Console.WriteLine("Wait handle released, thus cancelation was requested");
});

Console.ReadKey();

cts.Cancel();

Thread.Sleep(1000); // cancelation is non-instant

Console.WriteLine($"Task has been canceled. The status of the canceled task


't' is {t.Status}.");
Console.WriteLine($"Task has been canceled. The status of the canceled task
't2' is {t2.Status}.");
Console.WriteLine($"t.IsCanceled = {t.IsCanceled}, t2.IsCanceled =
{t2.IsCanceled}");
}

private static void CancelableTasks()


{
var cts = new CancellationTokenSource();
var token = cts.Token;
Task t = new Task(() =>
{
int i = 0;
while (true)
{
if (token.IsCancellationRequested) // task cancelation is cooperative,
no-one kills your thread
break;
else
Console.WriteLine($"{i++}\t");
}
});
t.Start();

// don't forget CancellationToken.None

Console.ReadKey();
cts.Cancel();
Console.WriteLine("Task has been canceled.");
}
}
}

You might also like