Параллельное выполнение асинхронных задач 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 шт):

Автор решения: aepot

Во-первых, как указали на ошибку, вы читаете файл в массив 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 ожидать нельзя, как следствие и нельзя их признать асинхронными из вызывающего кода.

→ Ссылка