Страницы

Поиск по вопросам

понедельник, 27 мая 2019 г.

Отображение процесса происходящего внутри функции

Не знаю как точно сформулировать вопрос.
Есть функция, которая выполняет какие-то действия. Она находится в "библиотеке классов". Я подключаю эту библиотеку к своему приложению. Запускаю эту функцию и хочу, чтобы в ProgressBar отображался ход выполнения этой процедуры из библиотеки. Как это правильно реализовать в подходе MVVM?
UPD: Вот пример по методу Vlad: Функция в библиотеке:
using System;
namespace ClassLib { public static class Service { public static void Foo(IProgress progress) { progress.Report(1); string s; for (int i = 1; i <= 99; i++) { for (int j = 0; j <= 50000; j++) s = j.ToString(); progress.Report(i); } progress.Report(100); } } }
ViewModel:
public class MainWindowViewModel: INotifyPropertyChanged { private int _progr; public int Progress { get { return _progr; } set { _progr = value;OnPropertyChanged("Progress"); } }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
public void StartFoo() { Service.Foo(new Progress(persent => Progress = persent)); }
}
View: XAML
...
c# code:
private void button_Click(object sender, RoutedEventArgs e) { MainWindowViewModel vm = (MainWindowViewModel)this.DataContext; vm.StartFoo(); }
Процесс отображается так : 0 пауза 100 %.


Ответ

Я бы посоветовал в следующее:
1.В библиотечный метод добавить параметр типа IProgress.
public class Service { public void Foo(IProgress progress) { progress.Report(1); DoSomeWork(); progress.Report(100); } }
2.В модель представления добавить свойство Progress и обработчик изменения прогресса
public class ViewModel { public int Progress { get; set; } // при установке значения вызывает PropertyChanged
private void HandleProgressChanged(int progress) { Progress = progress; }
private void StartFoo() { Service.Foo(new Progress(HandleProgressChanged)); } }
3.В представлении привязаться к свойству Progress.

UPD
Ну да. Я слишком упростил пример. Ваш код синхронный. Он выполняется в UI-потоке. Поэтому подвисает интерфейс окна. Его нужно запускать асинхронно: сделать библиотечный метод async или запускать его через Task.Run. Например, так:
public static async Task Foo(IProgress progress) { progress.Report(1); string s; for (int i = 1; i <= 99; i++) { for (int j = 0; j <= 50000; j++) s = j.ToString(); await Task.Delay(1);// это просто имитация бурной деятельности progress.Report(i); } progress.Report(100); }
public async Task StartFoo() { await Service.Foo(new Progress(persent => Progress = persent)); }
private async void button_Click(object sender, RoutedEventArgs e) { MainWindowViewModel vm = (MainWindowViewModel)this.DataContext; await vm.StartFoo(); }
Еще я бы посоветовал использовать команды, а не обработчики нажатия кнопок.

Комментариев нет:

Отправить комментарий