#.net #wpf #vb.net #multithreading #wait
#.net #wpf #vb.net #многопоточность #подождите
Вопрос:
Существует ли функция синхронного ожидания, которая не будет связывать пользовательский интерфейс с потоком в .NET WPF? Что-то вроде:
Sub OnClick(sender As Object, e As MouseEventArgs) Handles button1.Click
Wait(2000)
'Ui still processes other events here
MessageBox.Show("Is has been 2 seconds since you clicked the button!")
End Sub
Комментарии:
1. в обычном Win32 вы можете использовать MsgWaitForMultipleObjects для достижения этой цели.
Ответ №1:
Вы можете использовать DispatcherTimer
для такого рода вещей.
Редактировать: Это тоже может сработать…
private void Wait(double seconds)
{
var frame = new DispatcherFrame();
new Thread((ThreadStart)(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(seconds));
frame.Continue = false;
})).Start();
Dispatcher.PushFrame(frame);
}
( Dispatcher.PushFrame
документация.)
Начиная с .NET 4.5 вы можете использовать async
обработчики событий и Task.Delay
для получения такого же поведения. Просто позволить обновлению пользовательского интерфейса во время такого возврата обработчика Dispatcher.Yield
.
Комментарии:
1. В WPF вы демонстративно хотите использовать DispatcherTimer, поскольку его тики будут выполняться в потоке пользовательского интерфейса, позволяя вам изменять элементы управления пользовательского интерфейса. Если вы используете стандартный таймер, тики выполняются в своем собственном потоке, и вы получите несколько неприятных исключений, если попытаетесь коснуться элементов управления пользовательского интерфейса. 1
2. Можно ли в любом случае использовать таймер для выполнения встроенного ожидания. Кажется громоздким и трудным для чтения, когда вы разбиваете метод каждый раз, когда вам нужно подождать.
3. @PeterM: Поскольку я не слишком хорошо разбираюсь в вопросах потоковой обработки, возможно, вы захотите взглянуть на ссылку на модель потоковой обработки и
Dispatcher.PushFrame
метод, который может помочь вам упростить это.4. @PeterM: На самом деле, я думаю, что я только что получил решение, используя этот метод, смотрите Мой обновленный ответ. (Хотя я не говорю на VB …)
5. В качестве примера неблокирующего ожидания события в C #
Ответ №2:
Вот решение с Task.Delay
. Я использую это в модульных тестах для ViewModel
ов, которые используют DispatcherTimer
.
var frame = new DispatcherFrame();
var t = Task.Run(
async () => {
await Task.Delay(TimeSpan.FromSeconds(1.5));
frame.Continue = false;
});
Dispatcher.PushFrame(frame);
t.Wait();