У меня есть метод, который не может выполняться одновременно в нескольких потоках (он записывает в файл). Я не могу использовать 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 может быть)?