2015-07-06 2 views
0

Я работает приложение WPF и хотите сделать что-то вроде этого:Отражать изменения в приложении WPF динамически

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     TextBox textBox = new TextBox(); 
     mainGrid.Children.Add(textBox); 
     textBox.Text = "one"; 
     Thread.Sleep(1000); 
     textBox.Text = "two"; 
     Thread.Sleep(1000); 
     textBox.Text = "three"; 
     Thread.Sleep(1000); 
     textBox.Text = "four"; 
    } 
} 

На дисплее не загружается, пока вся эта обработка завершена, следовательно, у меня есть пробел, отвечать на запросы приложение до 3 секунд и текстовое поле со словом четыре после запуска вышеуказанного кода.

Я посмотрел на класс BackgroundWorker и попытался это:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     // Set up background worker object & hook up handlers 
     BackgroundWorker backgroundWorker; 
     backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); 
     backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); 

     backgroundWorker.RunWorkerAsync(); 
    } 

    private void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => 
     { 
      TextBox textBox = new TextBox(); 
      mainGrid.Children.Add(textBox); 
      textBox.Text = "one"; 
      Thread.Sleep(1000); 
      textBox.Text = "two"; 
      Thread.Sleep(1000); 
      textBox.Text = "three"; 
      Thread.Sleep(1000); 
      textBox.Text = "four"; 
     })); 
    } 

    private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     Debug.WriteLine("done"); 
    } 

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

ответ

4

Рассмотрите возможность использования async и await вместо:

private async void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    TextBox textBox = new TextBox(); 
    mainGrid.Children.Add(textBox); 
    textBox.Text = "one"; 
    await Task.Delay(1000); 
    textBox.Text = "two"; 
    await Task.Delay(1000); 
    textBox.Text = "three"; 
    await Task.Delay(1000); 
    textBox.Text = "four"; 
} 

Вот довольно неплохо tutorial по этому вопросу.

+0

Я пытаюсь понять, как асинк и ждать работы. Я нашел этот ответ: http://stackoverflow.com/a/7615440/2136312 Но не понял этого, программа ждет завершения асинхронного вызова. Тогда как это отличается от обычного ожидания? почему добавление async делает GUI отзывчивым? – codeln

+0

В двух словах, программирование async/await - это просто * простой способ записи «Задачи». Это позволяет пользовательскому интерфейсу реагировать, выполняя задачи в фоновом режиме. Как только задача будет завершена, она продолжит работу с кодом. См. [Здесь] (https://msdn.microsoft.com/en-us/library/hh191443.aspx) для более подробного объяснения. –

0

Асинхронный ожидание - лучший ответ, однако в этой ситуации можно использовать таймер.

System.Timers.Timer t; 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     t = new System.Timers.Timer(); 
     t.Elapsed += t_Elapsed; 
     t.Interval = 1000; 
     t.Start(); 
    } 

    int tickCount = 0; 

    void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     tickCount++; 
     switch (tickCount) 
     { 
      case 1: textBox.Text = "one"; break; 
      case 2: textBox.Text = "two"; break; 
      case 3: textBox.Text = "three"; break; 
      case 4: textBox.Text = "four"; break; 
      case 5: t.Stop(); break; 
     } 

    } 
1

Я согласен с предыдущими плакатами однако, если вы хотите использовать фон работника рассмотреть возможность взглянуть на этот учебник: http://www.wpf-tutorial.com/misc/multi-threading-with-the-backgroundworker/

[...] называется DoWork и общему правилу заключается в том, что вы не можете ничего трогать в пользовательском интерфейсе от этого события. Вместо этого вы вызываете метод ReportProgress(), который, в свою очередь, вызывает событие ProgressChanged, откуда вы можете обновить интерфейс. Как только вы закончите, вы назначаете результат работнику, а затем запускаете событие RunWorkerCompleted.

В основном пользовательский интерфейс должен работать на один нить. В противном случае вы теряете смысл.

Смежные вопросы