Как работает асинхронный C # 5.0? - PullRequest
3 голосов
/ 27 февраля 2011

Я пытаюсь понять, как работает новая асинхронная функция C # 5. Предположим, я хочу разработать атомарную функцию приращения для приращения целого числа в вымышленном IntStore. Эта функция выполняется только в одном потоке.

async void IncrementKey(string key) {
    int i = await IntStore.Get(key);
    IntStore.Set(key, i+1);
}

Мне кажется, что эта функция несовершенна. Два вызова IncrementKey могут вернуть один и тот же номер из IntStore (скажем, 5), а затем установить его на 6, потеряв при этом одно из приращений?

Как это можно переписать, если IntStore.Get для правильной работы асинхронен (возвращает Task)?

Производительность имеет решающее значение, есть ли решение, которое позволяет избежать блокировки?

1 Ответ

4 голосов
/ 27 февраля 2011

Если вы уверены, что вызываете свою функцию только из одного потока, то проблем быть не должно, поскольку одновременно может ожидаться только один вызов IntStore.Get. Это потому что:

await IncrementKey("AAA");
await IncrementKey("BBB");

второй IncrementKey не будет выполнен, пока не будет завершен первый IncrementKey. Код будет преобразован в конечный автомат. Если вы ему не доверяете, измените IntStore.Get (ключ) на:

async Task<int> IntStore(string str) {
    Console.WriteLine("Starting IntStore");
    await TaskEx.Delay(10000);
    return 0;
}

Вы увидите, что вторая Starting IntStore будет записана через 10 секунд после первой.

Цитировать здесь http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx The “await” operator ... means “if the task we are awaiting has not yet completed then sign up the rest of this method as the continuation of that task, and then return to your caller immediately; the task will invoke the continuation when it completes.”

...