Реализация TaskAwaiter - корректна ли?
От: Shmj Ниоткуда  
Дата: 07.10.18 05:06
Оценка:
В общем, задача стала для .Net 4.0 сделать ограниченную (упрощенную) поддержку async/await любой ценой. Есть NuGet-пакет для этого Microsoft.Bcl.Async. С ним проблема — он не работает на ограниченных привелегиях (в песочнице).

Однако для поддержки самого функционала он не нужен — достаточно пакетоа Microsoft.Bcl.Build (это минимум) ну и Microsoft.Bcl. Эти оба работают.

Ввиду того, что Microsoft.Bcl.Async никак не удалось заставить работать в песочнице, пришлось самому написать примитивнейший TaskAwaiter.

Честно сказать, дело было ночью и голова работает так себе. Как внутри устроено async/await детально не разбирался, но пока делал вроде стало более-менее понятно.

Задача была — чобы работал тот код, который уже написан с минимальными силами.

Собственно, вот такое получилось и оно вроде работает (не знаю, всегда ли будет установлен SynchronizationContext.Current, но в моих случаях он всегда установлен):

    internal class TaskAwaiter : INotifyCompletion
    {
        private readonly Task _task;

        public bool IsCompleted => _task.IsCompleted;

        public TaskAwaiter(Task task)
        {
            _task = task ?? throw new ArgumentNullException(nameof(task));
        }

        public void OnCompleted(Action continuation)
        {
            if (null == continuation)
                throw new ArgumentNullException(nameof(continuation));

            var synchronizationContext = SynchronizationContext.Current;

            _task.ContinueWith(t =>
            {
                synchronizationContext.Post(state => { continuation(); }, null);
            });
        }

        public void GetResult()
        {
            if (_task.IsCanceled)
                throw new TaskCanceledException();

            if (_task.IsFaulted)
            {
                var taskException = _task.Exception;
                var innerException = taskException?.InnerException;

                if (null != innerException)
                    throw innerException;

                throw taskException;
            }
        }
    }


Кто понимает принцип работы и что тут можно исправить?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.