В общем, задача стала для .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;
}
}
}
Кто понимает принцип работы и что тут можно исправить?