Лучший отвечающий
Доступ к элементам формы из потока

Вопрос
-
Добрый день
В приложении wpf .net 451 есть задача запустить в фоне несколько процессов, каждый из которых обращается к элементам формы и заполняет их. Для первичной реализации использовалась пара async-await. При этом всё работает.
Если использовать создание потоков посредством Parallel.For, то интерфейс пользователя почему-то блокируется и не особождается, пока все процессы не закончат работу.
Как это решить?Вот создание потоков:
Parallel.For(0, CountClient, i =>
{
StartClient(i);
});или
Parallel.For(0, CountClient, async i =>
{
await StartClientAsync(i);
});Вот обращение к элементам формы:
this.gridRun.Dispatcher.BeginInvoke((Action)(() =>
{
}
));или
await this.gridRun.Dispatcher.BeginInvoke((Action)(() =>
{
}
));- Изменено Алексей Екимов 16 апреля 2014 г. 16:53
16 апреля 2014 г. 16:42
Ответы
-
В методе Dispatcher.Invoke следует выполнять лишь короткую операцию, связанную непосредственно с UI. То есть нужно поместить его внутрь цикла, а в него - обновление прогрессбара. Thread.Sleep при этом должен быть вне Invoke.
- Помечено в качестве ответа Алексей Екимов 17 апреля 2014 г. 11:34
17 апреля 2014 г. 10:35
Все ответы
-
1. async/await, применённые к анонимному методу, не оказывают никакого эффекта, т.к. ожидается завершение вызова Parallel.For, а не анонимного метода.
2. Вызов Parallel.For синхронный, это значит, что он в целях производительности использует не только пул потоков, но и текущий поток, из которого он был вызван.
Parallel.For не поддерживает async/await, но можно запустить его в отдельном таске и уже дожидаться его завершения.
await Task.Run(() => Parallel.For(0, CountClient, i => { StartClient(i); }));
- Предложено в качестве ответа Sing1e 16 апреля 2014 г. 17:57
16 апреля 2014 г. 17:56 -
Спасибо, я так уже пробовал.
Не получилось:(
Есть ещё варианты?
17 апреля 2014 г. 7:24 -
Я приведу код, в котором возникает блокировка UI.
На форме wpf (.net 451) два элемента ProgressBar: pb1 и pb2.Как избежать блокировки UI?
---------------------------------------------------
private void btStart_Click(object sender, RoutedEventArgs e)
{
Task.Run(() =>
{
Parallel.Invoke(//Start first task
() =>
{
this.gridRun.Dispatcher.Invoke((Action)(() =>
{
for (int i = 0; i < 100; i++)
{
pb1.Value++; //ProgressBar 1
Thread.Sleep(50); //Эмуляция работы
}
}
));
},//Start second task
() =>
{
this.gridRun.Dispatcher.Invoke((Action)(() =>
{
for (int i = 0; i < 100; i++)
{
pb2.Value++; //ProgressBar 2
Thread.Sleep(50); //Эмуляция работы
}
}
));
}
);
}
);
}
---------------------------------------------------17 апреля 2014 г. 10:04 -
В методе Dispatcher.Invoke следует выполнять лишь короткую операцию, связанную непосредственно с UI. То есть нужно поместить его внутрь цикла, а в него - обновление прогрессбара. Thread.Sleep при этом должен быть вне Invoke.
- Помечено в качестве ответа Алексей Екимов 17 апреля 2014 г. 11:34
17 апреля 2014 г. 10:35 -
Да! Я только это понял и всё получилось.
Спасибо, оказалось наши решения совпали.
17 апреля 2014 г. 11:34