正确的方法来延迟任务的开始 [英] Correct way to delay the start of a Task

查看:181
本文介绍了正确的方法来延迟任务的开始的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想安排一个任务开始以x ms,并能够取消它开始(或只是在任务开始)之前。

I want to schedule a task to start in x ms and be able to cancel it before it starts (or just at the beginning of the task).

第一次尝试将类似于

var _cancelationTokenSource = new CancellationTokenSource();

var token = _cancelationTokenSource.Token;
Task.Factory.StartNew(() =>
    {
        token.ThrowIfCancellationRequested();
        Thread.Sleep(100);
        token.ThrowIfCancellationRequested();
    }).ContinueWith(t =>
    {
        token.ThrowIfCancellationRequested();
        DoWork();
        token.ThrowIfCancellationRequested();
    }, token);

但我觉得应该有一个更好的办法,因为这将使用一个线程,而在睡觉,其间也可能被取消。

But I feel like there should be a better way, as this would use up a thread while in the sleep, during which it could be canceled.

我有什么其他选择?

推荐答案

Damien_The_Unbeliever提到,异步CTP包括 Task.Delay 。幸运的是,我们有反射器:

Like Damien_The_Unbeliever mentioned, the Async CTP includes Task.Delay. Fortunately, we have Reflector:

public static class TaskEx
{
    static readonly Task _sPreCompletedTask = GetCompletedTask();
    static readonly Task _sPreCanceledTask = GetPreCanceledTask();

    public static Task Delay(int dueTimeMs, CancellationToken cancellationToken)
    {
        if (dueTimeMs < -1)
            throw new ArgumentOutOfRangeException("dueTimeMs", "Invalid due time");
        if (cancellationToken.IsCancellationRequested)
            return _sPreCanceledTask;
        if (dueTimeMs == 0)
            return _sPreCompletedTask;

        var tcs = new TaskCompletionSource<object>();
        var ctr = new CancellationTokenRegistration();
        var timer = new Timer(delegate(object self)
        {
            ctr.Dispose();
            ((Timer)self).Dispose();
            tcs.TrySetResult(null);
        });
        if (cancellationToken.CanBeCanceled)
            ctr = cancellationToken.Register(delegate
                                                 {
                                                     timer.Dispose();
                                                     tcs.TrySetCanceled();
                                                 });

        timer.Change(dueTimeMs, -1);
        return tcs.Task;
    }

    private static Task GetPreCanceledTask()
    {
        var source = new TaskCompletionSource<object>();
        source.TrySetCanceled();
        return source.Task;
    }

    private static Task GetCompletedTask()
    {
        var source = new TaskCompletionSource<object>();
        source.TrySetResult(null);
        return source.Task;
    }
}

这篇关于正确的方法来延迟任务的开始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆