DoEvents() висит

Как мне удалить этот вопрос? Сначала я думал, что проблема связана с DoEvents, но, как оказалось, это не так. Я разместил вопрос здесь: http://goo.gl/VpAEK с более подходящим описанием проблемы.

Спасибо - я ценю любые рекомендации о том, как справиться с этим...


Во-первых, я знаю этот вопрос, так как ранее была задана общая концепция - у меня (надеюсь) есть конкретный вариант, о котором нужно спросить. Я также начну говорить о том, что я понимаю конкретные причины, по которым не следует использовать Application.DoEvents() и уверяю всех сразу, что мы избегаем его, когда это возможно, и имеем несколько потоков, решающих проблемы (без участия Application.DoEvents()) на всем протяжении наше приложение.

При этом, это является частью структуры - и я думаю, что есть конкретные ситуации, в которых это имеет место.

Конкретный случай, о котором я спрашиваю, - это ситуация с одним потоком, с чисто пользовательским интерфейсом, где (как я понимаю) по определению - это нельзя сделать в фоновом потоке. Точнее говоря, мы загружаем / настраиваем ряд элементов пользовательского интерфейса в форме, для завершения которых иногда требуется 1-2 секунды, и я хочу, чтобы в ходе этого процесса обновлялась метка, указывающая, что происходит. На самом деле в фоновом потоке нет никакой тяжелой работы / работы, это все пользовательский интерфейс.

Если у меня нет вызова Application.DoEvents() после изменения текста 4 метки, метка не перерисовывается сама. Если кто-то может предложить альтернативу, которая решает эту проблему по-другому в чисто пользовательском интерфейсе, однопоточном окружении - я весь слух.

Проблема в том, что время от времени в тех случаях, когда я все еще пытаюсь определить, Application.DoEvents() просто не возвращается.

Я действительно понимаю все жалобы на метод DoEvents () (большинство из которых полностью действительны!!!) и различные проблемы, которые он может вызвать! Таким образом, в идеале, не вдаваясь в огромные дебаты о плюсах / минусах вызова DoEvents (как, кажется, делают почти все остальные темы на эту тему) - конкретный вопрос, на который я пытаюсь ответить, - может ли кто-нибудь придумать какую-либо причину почему DoEvents просто зависает? (т.е. не вернуть)?

Если вы хотите обсудить сам вызов DoEvents (), здесь есть отличное описание его сильных и слабых сторон: http://goo.gl/4BtZf

  • Наши пользователи сообщают, что, похоже, этого не происходит, когда они используют приложение, а скорее, только когда они некоторое время уходят от своего компьютера (возможно, с участием экранной заставки?) Мы заметили это при изменении разрешения экрана, когда удаленный просмотр компьютеров наших клиентов.
  • У нас есть пользователи, которые настаивают, что это происходит чаще, когда приложение свернуто.
  • У нас есть пользователи, которые настаивают, что это происходит чаще, когда приложение свернуто, и они выполняют некоторую работу в IE и / или Outlook.

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

После этого (буквально в первый раз, когда мы смогли воспроизвести его на месте), приложение зависло, а когда я подключился к процессу, оно зависло в строке Application.DoEvents(). 2-х строчный метод:

label.Text = "Foo"; Application.DoEvents();

Многочисленные дополнительные тесты (пытаясь выполнить те же действия) не смогли воспроизвести проблему.

Какие-либо предложения? Благодарю.


Изменить: это табу, чтобы попытаться получить ответ на вопрос, конкретно о DoEvents? Я относительно новичок в Stackru, и меня немного смущает, почему я уже получил два отрицательных голоса.

Я видел, как этот вопрос задавали много раз в других темах, и (по крайней мере, на мой взгляд, почти универсальный ответ - просто не используйте application.DoEvents()). Я специально старался быть внимательным в своем первоначальном вопросе и объяснить, почему мы использовали его в этом случае. В то же время я специально пытаюсь избежать еще одного обсуждения того, почему DoEvents не следует использовать. Если достаточное количество людей считает что-то плохой идеей, то просто ли это обсуждать на стеке? Опять же, я относительно новичок в этом форуме и пытаюсь понять правила игры здесь. Благодарю.

1 ответ

Неправильно полагать, что было бы неправильно использовать другие [фоновые] потоки для выполнения этой задачи. Если вы хотите идти по пути Application.DoEvents Все в порядке. Я не собираюсь сидеть здесь и говорить вам, что вы не должны использовать это, но вы должны, по крайней мере, рассмотреть возможность не использовать его в качестве возможной альтернативы. Как вы уже сказали, вы обновляете большое количество различных элементов пользовательского интерфейса. Вы не выполняете ни одной задачи пользовательского интерфейса, вы выполняете много (десятки, сотни, тысячи, что угодно) задач. У вас также есть отдельная задача, отвечающая за управление всеми этими небольшими задачами. Это управление меньшими задачами может быть выполнено либо в потоке пользовательского интерфейса, либо в потоке без пользовательского интерфейса. Если вы делаете это в потоке пользовательского интерфейса, то пользовательский интерфейс блокируется до тех пор, пока не будет завершено каждое действие вспомогательного пользовательского интерфейса. Если у вас есть поток, не относящийся к пользовательскому интерфейсу, который действует просто как "планировщик", добавляя несколько небольших задач пользовательского интерфейса для выполнения, тогда эти небольшие пользовательские задачи могут выполняться независимо и позволяют пользовательскому интерфейсу выполнять... все, что угодно... между некоторыми из этих задач.

Вот пример этого:

private void button1_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            Invoke(new MethodInvoker(() => updateLabel(i)));
            Invoke(new MethodInvoker(() => longerUITask(i)));
        }
    });
}

private void longerUITask(int i)
{
    //do databinding that will take a second or two
    Thread.Sleep(1000);
}

private void updateLabel(int i)
{
    label1.Text = i.ToString();
}

Будет ли это делать менее эффективно. Да, будет. Вы будете порождать другие потоки / задачи, управлять ими и т. Д. Однако то, что вы получаете за эту цену, является простой и эффективной гарантией того, что пользовательский интерфейс останется отзывчивым.

Другие вопросы по тегам