Показать прогресс в асинхронном ожидании

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

    private bool _isTaskStarted = false; 
    
    public bool IsTaskStarted
    {
        get { return _isTaskStarted; }
        set { _isTaskStarted = value; OnPropertyChanged(); }
    }

    private async void MethodCalledOnButtonClick()
    {
      IsTaskStarted = true; //this will tell UI to show progress 
      string result = await MyTimeConsumingMethod(param1, param2)
      IsTaskStarted = false;
    }
    
    private async Task<string> MyTimeConsumingMethod(List<string> collection, int count)
    {
      Task<string> t = Task.Run(()=>
      {
         //Task Delay is not working
         Task.Delay(2000);//Delay this task for 2 sec
    
        //Some time consuming code
        //Will create a pdf document and return a created pdf full path
        string returnValue = createdPdfFullPath;//Will have some value
    
        return returnValue ;
    
      });
      t.Wait();
    
      return await Task.FromResult(t.Result);
    }

Элемент пользовательского интерфейса может быть компонентом ProgressRing.

    <mah:ProgressRing 
    IsActive="{Binding IsTaskStarted , Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>

Даже если у меня есть отложенная задача на x секунд, элемент пользовательского интерфейса, включенный isTaskStarted, не виден. Но если я не установлю его значение на false, я увижу этот элемент. Но я хочу, чтобы этот элемент был виден во время выполнения MyTimeConsumingMethod

Как мне решить эту проблему? Может ли кто-нибудь указать мне правильное направление.


person Bhuban Shrestha    schedule 05.07.2021    source источник
comment
Это ваш настоящий код? Если нет, пожалуйста, предоставьте это. isTaskStarted — это локальная переменная, так как же поток пользовательского интерфейса будет читать значение? Если вы хотите, чтобы MyTimeConsumingMethod был асинхронным, не используйте Task.Wait внутри — это означает, что это совсем не асинхронно. Используйте return await Task.Run(...);   -  person Xerillio    schedule 05.07.2021
comment
Не совсем то, что мой фактический код, но isTaskStarted - это свойство, привязанное к элементу пользовательского интерфейса.   -  person Bhuban Shrestha    schedule 05.07.2021
comment
Старайтесь не слишком сильно менять код при публикации вопроса. Это очень затрудняет понимание проблемы. Пожалуйста, обновите вопрос, чтобы он был более ясным.   -  person Xerillio    schedule 05.07.2021
comment
Проблема в том, что ваш так называемый метод async на самом деле не является асинхронным. Проблемными операторами являются t.Wait(); и return await Task.FromResult(t.Result), которые оба блокируют до тех пор, пока задача не завершится, и вообще никаких асинхронных аспектов. Просто полностью удалите эти операторы, избавьтесь от async в объявлении метода и верните значение t.   -  person Peter Duniho    schedule 05.07.2021
comment
Покажите весь код, связанный с вашим вопросом, полностью. В том числе, если IsTaskStarted является свойством, то покажите, как вы его объявили и как задали привязку к нему в View.   -  person EldHasp    schedule 05.07.2021
comment
У вас есть привязка, установленная в свойстве IsActive. Как это работает? Если true, элемент mah:ProgressRing виден. Если ложно, не видно. Это верно?   -  person EldHasp    schedule 05.07.2021
comment
@ЭлдХасп да. если true, то будет отображаться кольцо прогресса, а если false, то оно будет невидимым в пользовательском интерфейсе.   -  person Bhuban Shrestha    schedule 05.07.2021
comment
Измените реализацию метода MyTimeConsumingMethod. Все, что должно быть в нем, это return await Task.Run (....);   -  person EldHasp    schedule 05.07.2021
comment
@EldHasp: return await Task.Run() в этом примере бессмысленно. Как я уже отмечал в своем комментарии выше, метод даже не обязательно должен быть async. Ему просто нужно вернуть объект Task<string>, возвращенный вызовом метода Task.Run().   -  person Peter Duniho    schedule 05.07.2021
comment
@ПитерДунихо. Да, я понимаю тебя. Но вопрос закрыт и правильный код показать не могу. Также неизвестно, насколько полно TC раскрыла свой код.   -  person EldHasp    schedule 05.07.2021
comment
@Ed: не уверен, какое отношение имеет закрытый вопрос к чему-либо, и верите ли вы, что сообщение включает в себя весь соответствующий код или нет. Сказать кому-то, что в нем должно быть только return await Task.Run (....);, всегда будет неправильно. Если это единственный оператор в методе, никогда нет смысла ждать выполнения задачи. Лучше всегда просто вернуть задачу.   -  person Peter Duniho    schedule 05.07.2021
comment
@PeterDuniho Почему это всегда будет неправильно? То, как я читаю эту статью от Дэвида Фаулера, ожидание, а не прямой возврат задачи обычно (читай: не всегда) предпочтительнее.   -  person Xerillio    schedule 05.07.2021
comment
@Xerillio: вы можете последовать совету Фаулера, если хотите. По моему мнению, ни один из четырех пунктов, которые он делает, на самом деле не так уж важен, и я бы всегда предпочел бы просто избежать дополнительных накладных расходов, связанных с переносом одной задачи на другую задачу. Возможно, мне следовало уточнить свои утверждения, чтобы было ясно, что это мое мнение. Код будет работать в любом случае. Я просто считаю бессмысленным делать это неэффективным способом.   -  person Peter Duniho    schedule 05.07.2021
comment
@PeterDuniho, я согласен с вами, что асинхронный MyTimeConsumingMethod в этом случае избыточен. И обычного метода, возвращающего строку, достаточно. Но чтобы показать правильную реализацию, нужно изменить как само объявление метода, так и то, как он вызывается в методе MethodCalledOnButtonClick. На мой взгляд, формат комментария не дает возможности для таких исправлений. Если бы вопрос не был закрыт, то можно было бы показать необходимые изменения в ответе.   -  person EldHasp    schedule 06.07.2021
comment
В своем комментарии я дал рекомендацию, достаточную для того, чтобы сделать код работоспособным (если я правильно понял причину ошибки). Для полноценного нормального рефакторинга кода формат комментария не дает необходимых возможностей.   -  person EldHasp    schedule 06.07.2021
comment
@EldHasp: формат комментария не дает возможности для таких исправлений -- и все же каким-то образом мне удалось чтобы точно описать эти изменения в комментариях. Забавно, как это получилось.   -  person Peter Duniho    schedule 06.07.2021
comment
@PeterDuniho, Но это одна или две инструкции. И даже это выглядит запутанно. А для нормального, правильного рефакторинга нужно полностью изменить реализацию двух методов. Это займет около дюжины строк кода.   -  person EldHasp    schedule 06.07.2021