Несколько обновлений асинхронного интерфейса в Silverlight - PullRequest
1 голос
/ 17 февраля 2012

Как выполнить несколько обновлений пользовательского интерфейса из обратного вызова Silverlight?

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

MainPage.xaml:

<Grid x:Name="LayoutRoot" Background="White" >
<TextBlock Height="23" Name="textBlock1" Text="TextBlock" VerticalAlignment="Top"/>
<Button Click="button1_Click" Content="Button" Height="23" Name="button1" Width="75"  />
</Grid>

MainPage.xaml.cs:

private void button1_Click(object sender, RoutedEventArgs e)
{
    textBlock1.Text = "1";
    // also tried Thread.Sleep(5000);
    Dispatcher.BeginInvoke(() => Thread.Sleep(5000));
    textBlock1.Text = "2";
}

Ответы [ 2 ]

1 голос
/ 17 февраля 2012

BeginInvoke выполняется асинхронно и поэтому возвращает и изменяет текст.

Непосредственно из документации MSDN: «BeginInvoke асинхронный; поэтому управление сразу же возвращается к вызывающему объекту послеПозвонил. "

Вместо этого в BeginInvoke добавьте обработку, которую вы хотите сделать.Таким образом, вы делаете Thread.Sleep, а затем добавляете изменения в текстовое поле.

BackgroundWorker также может связываться с событиями.Таким образом, когда пользовательский интерфейс обновляется или завершается событие BackGroundWorker, вы можете удалить следующий элемент.Вот почему вы должны использовать BgroundWorker

т.е.

BackgroundWorker w = new BackgroundWorker();
w.DoWork += (sender, args) => 
{
    Thread.Sleep(5000);
    Dispatcher.BeginInvoke(() => {
    //your code here
    }); 
};
w.RunWorkerAsync();
0 голосов
/ 17 февраля 2012

Silverlight использует очередь рабочих элементов для обработки рендеринга и логики в потоке пользовательского интерфейса. Поскольку ваша логика также выполняется в потоке пользовательского интерфейса (в вашем обработчике button_Click), средство визуализации не получает возможности рисовать экран до тех пор, пока не завершится выполнение вашего метода И внутренний цикл обработки сообщений не дойдет до рисования экрана.

Ваш BeginInvoke немедленно помещает вашу функцию в рабочую очередь Silverlight для выполнения в потоке пользовательского интерфейса (и немедленно возвращается). Порядок Silverlight обрабатывает это, вероятно, что-то вроде:

  • Пользователь нажимает кнопку, помещая событие щелчка в рабочую очередь
  • Silverlight видит событие click и вызывает button_Click (который помещает новое действие в рабочую очередь)
  • Обрабатывает следующий элемент рабочей очереди, который, вероятно, является вашим Thread.Sleep действием, останавливая поток пользовательского интерфейса на 5 секунд
  • Наконец Silverlight начинает рисовать на экране

То, что вы хотите сделать, - это создать новый поток для выполнения вашей работы, а затем BeginInvoke вернуться в поток пользовательского интерфейса:

var thread = new Thread(() => {
  Thread.Sleep(5000);
  Dispatcher.BeginInvoke(() => { 
    // update UI 
    textBox.Text = "2";
  });
});

textBox.Text = "1";
thread.Start();

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

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