创建冰冷的TaskCompletionSource?

Kri*_*erg 9 .net c# task-parallel-library async-await

我正在编写一个库,其中包括基于.Net Tasks的调度功能(不是标准TaskScheduler,IScheduler...).我正在使用TaskCompletionSource,并且Task.Status对于表示底层操作的状态至关重要,包括 TaskStatus.Created即已创建但尚未启动.我知道返回的任务通常应该很热,但对于我手动控制的代理任务,我确实最初想要它们Created.

不幸的是,我的初始状态TaskCompletionSource.TaskWaitingForActivation,即它已经过去了Created.换句话说,TaskCompletionSource支持两种状态,但我需要三种状态:

问题:如何获得Task可手动设置为三种不同状态的信息?即Task.Status可以设置为:

1)Created
2)WaitingForActivation/ WaitingForChildrenToComplete/ WaitingToRun/ Running
3)其中一个RanToCompletion/ Canceled/Faulted

下面的代码可以理解为抱怨类型不匹配.我可以通过改变new Task<TResult>来包装任务new Task<Task<TResult>>,但是要回到Task<TResult>Unwrap()必须的状态WaitingForActivation,并且解开的任务将具有状态,让我回到原点.

我将有大量的这些,所以阻止一个线程与Wait()每个不是一个选项.

我已经考虑过继承Task和覆盖成员(使用new),但是如果可能的话,给库用户一个实际的Task而不是一个很好DerivedTask,特别是因为我在许多其他地方也提出了常规的任务.

想法?

private TaskCompletionSource<TResult> tcs;

private async Task<TResult> CreateStartCompleteAsync()
{
    await tcs.Task;
    if (tcs.Task.IsCanceled)
    {
        throw new OperationCanceledException("");
    }
    else if // etc.
}

public ColdTaskCompletionSource()
{
    tcs = new TaskCompletionSource<TResult>();
    Task = new Task<TResult>(() => CreateStartCompleteAsync());
}
Run Code Online (Sandbox Code Playgroud)

错误:
*无法将lambda表达式转换为委托类型'System.Func',因为块中的某些返回类型不能隐式转换为委托返回类型
*无法将类型'System.Threading.Tasks.Task'隐式转换为'TResult "

nos*_*tio 6

虽然我同意@ usr在评论中的观点,但从技术上讲,您仍然可以拥有提供以下状态的实现:

  1. Created
  2. WaitingToRun
  3. RanToCompletion/Canceled/Faulted

为了避免阻塞线程与Task.Wait,你可以使用一个内部帮手TaskScheduler,它会首先要从其过渡的任务CreatedWaitingToRun,最终,已完成的国家之一.

下面的代码说明了这个概念.它只是经过了非常轻微的测试,可能不是完全线程安全的,也许可以改进以共享FakeTaskScheduler跨多个任务的单个实例.

public class ColdTaskCompletionSource
{
    public sealed class FakeTaskScheduler : TaskScheduler
    {
        Task _task;

        public FakeTaskScheduler()
        {
        }

        protected override void QueueTask(Task task)
        {
            _task = task;
        }

        protected sealed override bool TryDequeue(Task task)
        {
            if (task != _task)
                return false;

            _task = null;
            return true;
        }

        protected override IEnumerable<Task> GetScheduledTasks()
        {
            if (_task == null)
                yield break;
            yield return _task;
        }

        protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
        {
            return false;
        }

        public override int MaximumConcurrencyLevel
        {
            get { return 1; }
        }

        public bool Execute()
        {
            if (_task == null)
                return false;

            var task = _task;
            _task = null;
            return base.TryExecuteTask(task);
        }
    }

    readonly Task _task;
    readonly CancellationTokenSource _cts;
    readonly object _lock = new Object();
    readonly FakeTaskScheduler _ts = new FakeTaskScheduler();
    Action _completionAction = null;

    // helpers

    void InvokeCompletionAction()
    {
        if (_completionAction != null)
            _completionAction();
    }

    void Complete()
    {
        if (_task.Status != TaskStatus.WaitingToRun)
            throw new InvalidOperationException("Invalid Task state");
        _ts.Execute();
    }

    // public API

    public ColdTaskCompletionSource()
    {
        _cts = new CancellationTokenSource();
        _task = new Task(InvokeCompletionAction, _cts.Token);
    }

    public Task Task { get { return _task; } }

    public void Start()
    {
        _task.Start(_ts);
    }

    public void SetCompleted()
    {
        lock (_lock)
            Complete();
    }

    public void SetException(Exception ex)
    {
        lock (_lock)
        {
            _completionAction = () => { throw ex; };
            Complete();
        }
    }

    public void SetCancelled()
    {
        lock (_lock)
        {
            _completionAction = () =>
            {
                _cts.Cancel();
                _cts.Token.ThrowIfCancellationRequested();
            };
            Complete();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 巧妙的黑客. (4认同)