1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| public partial class Form1 : Form
{
/// <summary>
/// Tâche principale
/// </summary>
Task _t = null;
/// <summary>
/// Source d'annulation
/// </summary>
CancellationTokenSource _tks = new CancellationTokenSource();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (_t == null || _t.IsCompleted)
_t = Task.Factory.StartNew(le_thread, TaskCreationOptions.LongRunning);
else
{
System.Diagnostics.Debug.WriteLine("La tâche est en cours d'exécution, on ne va pas la lancer une seconde fois.");
}
}
public void le_thread()
{
Random r = new Random();
int res = 0;
for (int i = 1; i < 1000; i++)
{
this.BeginInvoke((Action)delegate() { info.Text = i.ToString(); });
for (int j = 1; j < 1000; j++)
{
for (int k = 1; k < 1000; k++)
{
res = k + r.Next();
//Lance l'exception "OperationCancelledExcpetion" pour annuler la tâche
//si la source d'annulation le demande.
_tks.Token.ThrowIfCancellationRequested();
}
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_t != null)
{
//La source d'annulation va demander l'arrêt de la tâche
_tks.Cancel();
//Attendre la fin de la tâche.
try { _t.Wait(); }
catch (AggregateException aggrExc)
{
//C'est l'inconvéniant du "Wait" : il encapsule l'exception avec un AggregateException
if (aggrExc.InnerException is OperationCanceledException)
{
System.Diagnostics.Debug.WriteLine("La tâche a été annulée");
//Ici, _t.IsCancelled vaut true
}
else
{
System.Diagnostics.Debug.WriteLine("Une autre erreur a eu lieu dans la tâche.");
//Ici, _t.IsFaulted vaut true
}
}
//Ici, ça c'est fini proprement normalement. Dans tous les cas, ici _t.IsCompleted vaut true
}
}
} |