Вот пример того, как вы можете это сделать. Чтобы немного упростить это, я добавил элементы управления непосредственно в конструктор MainWindow
, но я бы предпочел сделать это с XAML.
public MainWindow()
{
InitializeComponent();
var progressBar = new ProgressBar();
progressBar.Height = 40;
progressBar.Width = 200;
progressBar.Margin = new Thickness(100, 100, 100, 100);
Task.Factory.StartNew(() =>
{
// getLinks();
for (var i = 0; i < 5; i++)
{
Dispatcher.Invoke(new Action(() => { progressBar.Value += 20; }));
Thread.Sleep(500);
}
});
var stackPanel = new StackPanel();
stackPanel.Children.Add(progressBar);
Content = stackPanel;
}
Сначала я добавляю ProgressBar
где-нибудь на интерфейсе, чтобы сделать его видимым для этой демонстрации, а затем добавляю его к новому StackPanel
, это может быть любая панель вообще, в этом случае это не имеет значения.
Чтобы загрузить ссылки в другом потоке, я создаю новый Task
, который является частью TPL
( Task Parallel Library ) в .NET 4.0. В этом случае я симулирую, что getLinks()
требуется 5 * 500 миллисекунд для запуска, и что на самом деле это пять ссылок, которые будут загружены, следовательно, 20% за каждую итерацию.
Затем я добавляю 20
к значению progressBar
, что указывает на то, что оно увеличилось на 20%.
Эта строка может немного смущать вас
Dispatcher.Invoke(new Action(() => { progressBar.Value += 20; }));
Но на самом деле это довольно распространено, когда вы выполняете многопоточное программирование с помощью GUI. Таким образом, проблема в том, что вы находитесь в другом потоке, мы запустили Task
, который будет работать в отдельном потоке, и вы не можете обновить ваш поток пользовательского интерфейса из другого потока. Так что вам нужно что-то, что называется Dispatcher
, и это доступно из вашего Window
-класса.
Затем вы Invoke
выполняете действие, а это значит, что вы просто говорите: «Запустите этот фрагмент кода для меня в этой теме».
И если вы хотите отобразить MessageBox
, когда все загружено, вы можете просто добавить MessageBox.Show("Loaded!");
после for
-loop.