У меня есть метод, который не может выполняться одновременно в нескольких потоках (он записывает в файл). Я не могу использовать lock
, потому что метод async
. Как избежать вызова метода в другом потоке? Вместо того, чтобы вызывать его второй раз, программа должна дождаться завершения предыдущего вызова (также асинхронно).
Например, создайте новое консольное приложение С# со следующим кодом:
using System;
using System.IO;
using System.Threading.Tasks;
namespace ConsoleApplication1 {
internal class Program {
private static void Main () {
CallSlowStuff();
CallSlowStuff();
Console.ReadKey();
}
private static async void CallSlowStuff () {
try {
await DoSlowStuff();
Console.WriteLine("Done!");
}
catch (Exception e) {
Console.WriteLine(e.Message);
}
}
private static async Task DoSlowStuff () {
using (File.Open("_", FileMode.Create, FileAccess.Write, FileShare.None)) {
for (int i = 0; i < 10; i++) {
await Task.Factory.StartNew(Console.WriteLine, i);
await Task.Delay(100);
}
}
}
}
}
В этом примере второй вызов CallSlowStuff
выдает исключение, потому что он не может получить доступ к уже открытому файлу. Добавление lock
не является опцией, потому что lock
и async
не смешиваются. (Main
метод должен считаться нечувствительным. В реальном приложении CallSlowStuff
- это метод интерфейса, который можно назвать где угодно.)
Вопрос. Как сделать последующие вызовы CallSlowStuff
ждать завершения текущего выполняемого вызова без блокировки основного потока? Может ли это быть сделано с помощью async/wait и задач (и Rx может быть)?