Прохождение:

https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

А также

Как привязать кнопку WPF к команде в ViewModelBase?

Я придумал следующий код для асинхронного (или синхронного?) Чтения и рендеринга содержимого файла в окно:

class AppliedJobsViewModel
{
    private TexParser texParser; 

    private ICommand _openTexClick;
    public ICommand OpenTexClick
    {
        get
        {
            return _openTexClick ?? (_openTexClick = new CommandHandler(() => ReadAndParseTexFile(), () => CanExecute));
        }
    }
    public bool CanExecute
    {
        get
        {
            // check if executing is allowed, i.e., validate, check if a process is running, etc. 
            return true;
        }
    }

    public async Task ReadAndParseTexFile()
    {
        if (texParser == null)
        {
            texParser = new TexParser();
        }
        // Read file asynchronously here
        await ReadAndParseTexFileAsync();            
        string[][] appliedJobs = texParser.getCleanTable();
    }

    private async Task ReadAndParseTexFileAsync()
    {
        texParser.ReadTexFile();
        await Task.Delay(100);
    }

    public ObservableCollection<AppliedJob> AppliedJobs {
        get;
        set;
    }
}

Который "работает", но мне не нравится Task.Delay (100) (постоянное время ожидания).

VS также сообщает мне в строке:

    return _openTexClick ?? (_openTexClick = new CommandHandler(() => ReadAndParseTexFile(), () => CanExecute));

«Поскольку этого вызова не ожидается, выполнение этого метода продолжается до завершения вызова».

Но именно этот метод привязывает код к представлению wpf. Разве это не асинхронный режим по умолчанию?

0
Sebi 3 Окт 2020 в 17:34

1 ответ

Лучший ответ

Простое удаление асинхронного кода в сигнатуре метода или задачи не означает, что вы делаете что-либо асинхронно.

Прочитай это:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/using-async-for-file-access

Обратите внимание, что это не просто случай добавления асинхронности к имени, а делает File.ReadAllTextAsync асинхронным.

Вы должны прочитать об async и подождать. например https://blog.stephencleary.com/2012/02/async- and-await.html

Это сложная тема. Чтобы понять, нужно внимательно прочитать и подумать.

Прочитав это, пересмотрите свой код.

В этом предупреждении ваш ide сообщал вам, что ваш код синхронный.

У вас есть синхронный код, читающий этот файл.

Вставка в него кода await some-other-code не делает код чтения файла асинхронным, это просто означает, что ide видит задачу await. Бессмысленная задача ожидания.

Теперь вы знаете, что это бессмысленно.

Выиграть

await Task.Delay(100);

Заменив код чтения файла на

 string contents = await File.ReadAllTextAsync(filePath); 

Мог сделать чтение файла асинхронным.

Если это большой файл, считываемый в память, то простое его чтение может иметь значительные накладные расходы, и ваш пользовательский интерфейс может оставаться отзывчивым.

Если бы вы выполняли существенную обработку файла, вам, вероятно, было бы лучше передать это в фоновый поток.

Ты можешь сделать

 await Task.Run(() => ProcessFileText(someurl));

Здесь ProcessFileText будет Task или, возможно, Task и вернет строку или массив строк. Он будет работать в фоновом потоке и вернется после завершения. Поскольку это другой поток, он не остановит ваш пользовательский интерфейс, если для его работы потребуется время.

Обратите внимание, что, поскольку теперь она не находится в потоке пользовательского интерфейса, эта задача не может читать или записывать свойства пользовательского интерфейса, иначе вы получите ошибки потоковой передачи. Код в строке (ах) после этого await возвращается в поток пользовательского интерфейса.

2
Andy 4 Окт 2020 в 11:12