Task sequencing and re-entracy

前端 未结 3 1350
执笔经年
执笔经年 2020-11-27 04:11

I\'ve got the following scenario, which I think might be quite common:

  1. There is a task (a UI command handler) which can complete either synchronously or asy

3条回答
  •  渐次进展
    2020-11-27 04:55

    I almost forgot it's possible to construct a Task manually, without starting or scheduling it. Then, "Task.Factory.StartNew" vs "new Task(...).Start" put me back on track. I think this is one of those few cases when the Task constructor may actually be useful, along with nested tasks (Task>) and Task.Unwrap():

    // AsyncOp
    class AsyncOp
    {
        Task _pending = Task.FromResult(default(T));
    
        public Task CurrentTask { get { return _pending; } }
    
        public Task RunAsync(Func> handler, bool useSynchronizationContext = false)
        {
            var pending = _pending;
            Func> wrapper = async () =>
            {
                // await the prev task
                var prevResult = await pending;
                Console.WriteLine("\nprev task result:  " + prevResult);
                // start and await the handler
                return await handler();
            };
    
            var task = new Task>(wrapper);
            var inner = task.Unwrap();
            _pending = inner;
    
            task.RunSynchronously(useSynchronizationContext ?
                TaskScheduler.FromCurrentSynchronizationContext() :
                TaskScheduler.Current);
    
            return inner;
        }
    }
    

    The output:

    Test #1...
    
    prev task result:  0
    this task arg: 1000
    
    prev task result:  1000
    this task arg: 900
    
    prev task result:  900
    this task arg: 800
    
    Press any key to continue to test #2...
    
    
    prev task result:  800
    this task arg: 100
    
    prev task result:  100
    this task arg: 200
    

    It's now also very easy to make AsyncOp thread-safe by adding a lock to protect _pending, if needed.

    Updated, this has been further improved with cancel/restart logic.

提交回复
热议问题