在Task运营进程中,大家能够通过.Net 4中的内置方法来裁撤Task的运营。

创制叁个可撤销的Task要求选拔上边包车型客车大器晚成部分指标:

1.System.Threading.CancellationTokenSource实例

CancellationTokenSource tokenSource = new CancellationTokenSource();

2.通过CancellationTokenSource.Token属性获得叁个注销令牌

CancellationToken token = tokenSource.Token;

3.创造Task对象,何况在布局函数字传送入Action(或者Action<T>)信托作为第八个参数,CancellationToken凯旋门074网址,用作第三个参数(重要)

Task task = new Task(() =>
{
// do something
}, token);
task.Start();

 4.创制Task对象也能够透过调用System.Threading.Tasks.TaskFactory澳门凯旋门注册网址,.aspx卡塔尔 类提供的静态方法

Task task = Task.Factory.StartNew(() =>
{
    // do something ......
}, token);

 

风流浪漫旦想要打消Task的周转,除了要调用CancellationTokenSource实例的Cancel()措施之外,大家的Action委托中还要求检查测量试验CancellationToken的撤销状态并编写相应代码(抛出卓殊卡塔尔国来阻止Task的运行。

能够经过以下办法来检查测量检验Task撤除状态:

1.通过轮询的不二等秘书技术检查测CancellationToken澳门凯旋门游戏网址,撤回标识,该操作看似于轮询异步操作的IAsyncResult.IsCompleted情形,也是透过在循环中推断CancellationToken.IsCancellationRequested性情来检验Task是或不是被收回,倘使为True则在Action委托中抛出特别来裁撤继续运营Task。 

static void Main(string[] args)
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;
    Task task = new Task(() =>
    {
        while (true)
        {
            if(token.IsCancellationRequested)
            {
                // 释放资源操作等等...
                throw new OperationCanceledException(token);
            }
            Console.Write(".");
            Thread.Sleep(100);
        }
    }, token);

    Console.WriteLine("Task is Running.");
    Console.WriteLine("Press anykey to cancel task.");    

    task.Start();

    Console.ReadKey(true);
    Console.WriteLine();
    Console.WriteLine("Cancelling task.");
    tokenSource.Cancel();            

    Console.WriteLine("Main method complete.");
    Console.WriteLine("Press enter to finish.");
    Console.ReadLine();
}

 

假定没有必要释放系统财富,那么能够一向调用CancellationToken.ThrowIfCancellationRequested()方式,其促成如下:

[__DynamicallyInvokable]
public void ThrowIfCancellationRequested()
{
    if (this.IsCancellationRequested)
    {
        this.ThrowOperationCanceledException();
    }
}

创建一个可取消的Task需要用到下面的一些对象。 示例:

while (true)
{
    token.ThrowIfCancellationRequested();
    Console.Write(".");
    Thread.Sleep(100);
}

 

2.通过委托(Delegate)来检查评定Task是还是不是吊销,注册三个在裁撤CancellationToken时调用的信托,当CancellationTokenSource发送撤销伏乞时,该信托即会运行,大家可以在信托方法中达成公告作用等等。

static void Main(string[] args)
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;
    Task task = new Task(() =>
    {
        while (true)
        {
            token.ThrowIfCancellationRequested();
            Console.Write(".");
            Thread.Sleep(100);
        }
    }, token);

    token.Register(() => { Console.WriteLine("The delegate is triggered."); });

    Console.WriteLine("Task is Running.");
    Console.WriteLine("Press anykey to cancel task.");

    task.Start();

    Console.ReadKey(true);
    Console.WriteLine();
    Console.WriteLine("Cancelling task.");
    tokenSource.Cancel();

    Console.WriteLine("Main method complete.");
    Console.WriteLine("Press enter to finish.");
    Console.ReadLine();
}

 

3.用WaitHandle来检查实验Task是不是打消,当在CancellationToken.WaitHandle创建一个可取消的Task需要用到下面的一些对象。上调用创建一个可取消的Task需要用到下面的一些对象。WaitOne()措施时,会阻止当前线程实行,直到该CancellationToken收到到裁撤央求标识时,被token阻止的Task线程才会自由并继续推行。

三个Task实例使用同三个CancellationToken时,当CancellationToken收取到打消伏乞标识时,全体在构造函数中选择该token实例化的Task都会被打消。WaitOne(int
millisecondsTimeout)
创建一个可取消的Task需要用到下面的一些对象。可以接收等待皮秒数作为参数,超越等待时间将会释放阻止的线程。

不管WaitOne(int
millisecondsTimeout)
设置多少长度的等待时间,只要CancellationToken选择到撤除央浼标识时Task都会吊销,而意气风发旦应用Thread.Sleep(100000)张开线程等待时,那么即便CancellationToken吸收接纳到撤销伏乞标志,该Task也会等到Thread.Sleep试行到位才会Cancel。

static void Main(string[] args)
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;

    Task task = new Task(() =>
    {
        while (true)
        {                    
            token.ThrowIfCancellationRequested();
            Console.Write(".");
            Thread.Sleep(100);
        }
    }, token);

    Task task1 = new Task(() =>
    {
        token.WaitHandle.WaitOne();
        Console.WriteLine("WaitHandle released.");
    }, token);

    Console.WriteLine("Task is Running.");
    Console.WriteLine("Press anykey to cancel task.");

    task.Start();
    task1.Start();

    Console.ReadKey(true);
    Console.WriteLine();
    Console.WriteLine("Cancelling task.");
    tokenSource.Cancel();

    Console.WriteLine("Main method complete.");
    Console.WriteLine("Press enter to finish.");
    Console.ReadLine();
}

 

4.通过Task的IsCancelled质量来决断Task是不是被收回,假若Task实例化时构造函数未有传到CancellationToken对象,则裁撤Task运维之后经过Task.IsCanceled属性获取到的值依然False而不是TrueTask.ContinueWith()艺术若无传到CancellationToken指标,则Task固然是废除实行也会继续实行Task.ContinueWith()艺术的Action委托,纵然传入与Task相近的CancellationToken对象,则Task撤除试行后Task.ContinueWith()措施中的Action委托也不会继续实行。

{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;
    Task task = new Task(() =>
    {
        try
        {
            Console.WriteLine("Task: Running");
            Thread.Sleep(5000);
            Console.WriteLine("Task: ThrowIfCancellationRequested");
            token.ThrowIfCancellationRequested();
            Thread.Sleep(2000);
            Console.WriteLine("Task: Completed");
        }
        catch (Exception exception)
        {
            Console.WriteLine("Task: " + exception.GetType().Name);
            throw;
        }
    }, token);

    task.ContinueWith(t => Console.WriteLine("ContinueWith: tokenSource.IsCancellationRequested = {0}, task.IsCanceled = {1}, task.Exception = {2}", tokenSource.IsCancellationRequested, t.IsCanceled, t.Exception == null ? "null" : t.Exception.GetType().Name));
    task.Start();

    Thread.Sleep(1000);

    Console.WriteLine("Main: Cancel");
    tokenSource.Cancel();

    try
    {
        Console.WriteLine("Main: Wait");
        task.Wait();
    }
    catch (Exception exception)
    {
        Console.WriteLine("Main: Catch " + exception.GetType().Name);
    }

    Console.WriteLine("Main: task.IsCanceled = {0}", task.IsCanceled);
    Console.WriteLine("Press any key to exit...");

    Console.ReadKey(true);
}

 

经超过实际施Task.WaitAll(task卡塔尔,Task.WaitAny(task卡塔尔国,task.Result,task.Wait(卡塔尔出现了极其抛出的是一个System.AggregateException;

透超过实际行task.Wait(CancellationToken卡塔尔国出现了要命抛出的是二个OperationCanceledException;

相关文章