Это может показаться немного сумасшедшим, но это подход, который я рассматриваю как часть более крупной библиотеки, если я могу быть уверенным, что это не вызовет странного поведения.
Подход:
Запустите асинхронный код пользователя с SynchronizationContext
, который отправляется в пул потоков. Код пользователя выглядит примерно так:
async void DoSomething()
{
int someState = 2;
await DoSomethingAsync();
someState = 4;
await DoSomethingElseAsync();
// someState guaranteed to be 4?
}
Я не уверен, будет ли доступ к someState
потокобезопасным. Хотя код будет работать в одном "потоке", так что операции, фактически, полностью упорядочены, его все равно можно разделить на несколько потоков под капотом. Если мое понимание правильное, заказ должен быть безопасным на x86, и поскольку переменная не является общей, мне не нужно беспокоиться о оптимизации компилятора и т.д.
Что еще более важно, я обеспокоен тем, будет ли это гарантировано потокобезопасным в моделях памяти ECMA или CLR.
Я абсолютно уверен, что мне нужно будет вставить барьер памяти перед выполнением очереди в очереди, но я не полностью уверен в своих рассуждениях здесь (или что этот подход может быть неработоспособным по совершенно разным причинам).