Является ли асинхронный метод синхронным, если ожидание Задача никогда не возвращается? - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть конструктор, который вызывается в потоке пользовательского интерфейса в моем приложении WPF.Внутри него он вызывает асинхронный метод, но это должно выполняться синхронно.Я попытался подождать, но это вызвало тупик, и я понимаю, почему.Поэтому я ввел аргумент, который указывает, должен ли метод выполняться асинхронно или синхронно.Примерно так:

// constructor that is called on UI thread
public MyClass()
{
    Method1(false).Wait();
}

public async Task Method1(bool runAsync)
{
    await Method2(runAsync);
}

public async Task Method2(bool runAsync)
{
    if (runAsync)
    {
        await Task.Run(() => Thread.Sleep(1000));
    }
    else
    {
        Thread.Sleep(1000);
    }
}

Я не хочу использовать ConfigureAwait, потому что я хочу, чтобы все работало в потоке пользовательского интерфейса.Will Method1 (false) .Wait ();когда-либо вызывать тупик (это безопасно использовать)?Я много тестировал, но это не так, но я не уверен.Наконец, мой реальный вопрос: если 'await Task.Run (...' никогда не выполняется, мой метод полностью синхронен? Я нашел несколько сообщений на эту тему, но ни один из них не отвечает прямо на мой вопрос.

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Вместо того, чтобы бороться с асинхронными вещами на этапе строительства (ваше решение по блокировке не очень хорошо), почему бы не написать асинхронную фабрику для выброса этих объектов?

class MyClass
{
    public MyClass()
    {

    }

    public async Task Method2(bool runAsync)
    {
        //async immediately
        await Task.Delay(1000); //no Thread.Sleep. Blocking code != good
    }
}

, а затем

public MyClassFactory
{
    public async Task<MyClass> GetAsync()
    {
        var c = new MyClass();
        await c.Method2();
        return c;
    }
}
0 голосов
/ 28 февраля 2019

У меня есть конструктор, который вызывается в потоке пользовательского интерфейса в моем приложении WPF.Внутри него он вызывает асинхронный метод, но это должно быть сделано синхронно.

Я остановлю вас прямо здесь.Лучшее решение - , а не для запуска синхронного / блокирующего кода в потоке пользовательского интерфейса.Это ухудшает ваш пользовательский опыт.Вместо этого вы должны реструктурировать свой код так, чтобы вы никогда не оказывались в такой ситуации.

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

Решение состоит в том, чтобы спроектировать промежуточное состояние для вашего пользовательского интерфейса, например, сообщение «загрузка ...» или спиннер.Затем, когда ваш код запускается, он может синхронно / немедленно отображать состояние «загрузки» (и start асинхронная операция), а когда поступают асинхронные данные, код обновляет пользовательский интерфейсв «окончательное» состояние.

Я обсуждаю этот шаблон более подробно в моей статье о асинхронных данных MVVM .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...