Параллельное выполнение асинхронных задач C#
Имеется button1, при нажатии на который должна запуститься параллельная обработка файлов. Код:
private async void button1_ClickAsync(object sender, EventArgs e)
{
for (int i = 0; i < paths.Count; i++)
{
await Processing(paths[i]);
}
}
Сам метод:
public async Task Processing(string path)
{
byte[] newFile; //Переменная для записи нового файла
using (FileStream f = File.OpenRead(path))
{
byte[] openFile = new byte[f.Length];
await f.ReadAsync(openFile, 0, openFile.Length);
//Обработка файла, в ней же и записываются значения в newFile
}
File.Delete(path); //Можно вместо этого изменить FileMode в следующей строке, но пока что не до этого
using (FileStream f = new FileStream(path, FileMode.Create))
{
await f.WriteAsync(newFile, 0, newFile.Length);
}
processed++;
label10.Text = "Обработано файлов: " + processed;
}
Обрабатывает несколько файлов и сохраняет пустые файлы. Ощущение, что файлы читаются неправильно, либо неправильно записываются. Ошибка в том, что делаю методы параллельно или в асинхронности самих методов? Спасибо.
Ответы (1 шт):
Во-первых, как указали на ошибку, вы читаете файл в массив openFile, а записываете массив newFile, а в нём пусто.
Во-вторых, вот то же самое, только код короче. С выносом обработки данных в отдельный поток, чтобы не вешать приложение. Допустим, обработка данных выполняется ощутимо долго. Допустим, количество байт в записываемом файле такое же, как в прочитанном.
private async Task ProcessFileAsync(string path)
{
byte[] bytes = await File.ReadAllBytesAsync(path);
await Task.Run(() => ProcessData(bytes));
await File.WriteAllBytesAsync(path, bytes);
processed++;
label10.Text = "Обработано файлов: " + processed;
}
private void ProcessData(byte[] bytes)
{
// здесь синхронная обработка данных массива с записью изменений в этот же массив
}
В-третьих, обработка файлов происходит последовательно, один за другим. Можно сделать параллельно, но это имеет смысл только если чтение и запись файла занимают немного времени по сравнению с обработкой данных.
private async void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
Task[] tasks = new Task[paths.Count];
for (int i = 0; i < paths.Count; i++)
{
tasks[i] = ProcessFileAsync(paths[i]);
}
await Task.WhenAll(tasks);
button1.Enabled = true;
}
Вот теперь обработка полностью будет выполняться действительно параллельно.
Кстати, суффикс ...Async стоит дописывать только к ожидабельным (awaitable) методам, то есть к которым можно применить await. Методы типа async void ожидать нельзя, как следствие и нельзя их признать асинхронными из вызывающего кода.