Как зайти в Даркнет?!
25th January, 01:11
6
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
894
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
913
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4396
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Выбрали компактный рамках/нарезание резьбы - MessageBox отображается над другими элементами управления после того, как опция
Я работаю над приложением, которое захватывает и устанавливает кучу обновлений с внешнего сервера,и мне нужна помощь с потоковой обработкой. Пользователь выполняет этот процесс:
- Нажимает кнопку
- Метод проверяет наличие обновлений, возвращается счетчик.
- Если больше 0, то спросите пользователя, если они хотят установить с помощью MessageBox.Show().
- Если да, то он проходит через цикл и вызывает BeginInvoke() в методе run() каждого обновления, чтобы запустить его в фоновом режиме.
- В моем классе обновления есть некоторые события, которые используются для обновления индикатора выполнения и т. д.
Обновления индикатора выполнения в порядке, но MessageBox не полностью очищается от экрана, потому что цикл обновления начинается сразу после нажатия пользователем кнопки да (см. снимок экрана ниже).
- Что я должен сделать, чтобы сделать messagebox исчезнуть мгновенно до начала цикла обновления?
- Должен ли я использовать потоки вместо BeginInvoke()?
- Должен ли я выполнять начальную проверку обновления в отдельном потоке и вызывать MessageBox.Show() из этого потока?
Код
// Button clicked event handler code...
DialogResult dlgRes = MessageBox.Show(
string.Format("There are {0} updates available.\n\nInstall these now?",
um2.Updates.Count), "Updates Available",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2
);
if (dlgRes == DialogResult.Yes)
{
ProcessAllUpdates(um2);
}
// Processes a bunch of items in a loop
private void ProcessAllUpdates(UpdateManager2 um2)
{
for (int i = 0; i < um2.Updates.Count; i++)
{
Update2 update = um2.Updates[i];
ProcessSingleUpdate(update);
int percentComplete = Utilities.CalculatePercentCompleted(i, um2.Updates.Count);
UpdateOverallProgress(percentComplete);
}
}
// Process a single update with IAsyncResult
private void ProcessSingleUpdate(Update2 update)
{
update.Action.OnStart += Action_OnStart;
update.Action.OnProgress += Action_OnProgress;
update.Action.OnCompletion += Action_OnCompletion;
//synchronous
//update.Action.Run();
// async
IAsyncResult ar = this.BeginInvoke((MethodInvoker)delegate() { update.Action.Run(); });
}
Скриншот
Ваш UI не обновляется, потому что вся работа происходит в потоке пользовательского интерфейса. Ваш призыв к:
this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); })
это говорит вызвать update.Action.Run() в потоке, который создал "this" (ваша форма), который является потоком пользовательского интерфейса.
Application.DoEvents()
это действительно даст потоку UI шанс перерисовать экран, но я бы хотел создать новый делегат и вызвать BeginInvoke на этом.
Это приведет к выполнению функции update.Action.Run() в отдельном потоке, выделенном из пула потоков. Затем вы можете продолжать проверять IAsyncResult до тех пор, пока обновление не будет завершено, запрашивая объект update для его выполнения после каждой проверки (потому что вы не можете позволить другому потоку обновить прогресс bar/UI),, а затем вызвать Application.DoEvents().
Вы также должны позвонить EndInvoke() после этого, иначе вы можете в конечном итоге утечка ресурсов
Я также хотел бы поставить кнопку отмены в диалоге прогресса и добавить тайм-аут, в противном случае, если обновление застрянет (или займет слишком много времени), то ваше приложение будет заблокировано навсегда.
@ John Sibly
Единственное задокументированное исключение из правила, о котором я знаю, находится в формах Windows, где вам официально разрешено звонить Control.BeginInvoke, не беспокоясь о вызове Control.EndInvoke.
Однако во всех других случаях, когда вы имеете дело с асинхронным шаблоном Begin/End, вы должны предположить, что он будет протекать, как вы и сказали.