Приложение WinForm UI зависает во время продолжительной операции

Покажите им их собственный код от 6 месяцев назад. Если они не могут понять и обрисовать в общих чертах точно, что это делает в течение 2 - 4 минут, Ваше мнение было, вероятно, высказано.

24
задан BoltClock 14 September 2012 в 10:31
поделиться

4 ответа

Вам необходимо выполнить длительную операцию в фоновом потоке.

Есть несколько способов сделать это.

  1. Вы можете поставить вызов метода в очередь для выполнения в потоке пула потоков. (См. здесь ):

     ThreadPool.QueueUserWorkItem (новый WaitCallback (YourMethod));
    

    В .NET 4.0 вы можете использовать TaskFactory :

     Task.Factory.StartNew (() => YourMethod ());
    

    А в .NET 4.5 и новее вы можете (и должны, а не TaskFactory.StartNew () ) использовать Task.Run () :

     Task.Run (() => Ваш метод ());
    
  2. Вы можете использовать BackgroundWorker для большего контроля над методом, если вам нужны такие вещи, как обновления хода выполнения или уведомление о его завершении. Перетащите элемент управления BackgroundWorker в форму и прикрепите свой метод к событию dowork. Затем просто запустите воркер, когда захотите запустить свой метод. Конечно, вы можете создать BackgroundWorker вручную из кода, просто помните, что от него нужно избавиться, когда вы закончите.

  3. Создайте совершенно новый поток для вашей работы. Это наиболее сложный вариант, и в нем нет необходимости, если вам не нужен действительно точный контроль над потоком. См. Страницу MSDN в классе Thread , если вы хотите узнать об этом.

Помните, что с любым потоком вы не можете обновить графический интерфейс или изменить любые элементы управления графическим интерфейсом из фоновый поток. Если вы хотите сделать что-либо в графическом интерфейсе, вы должны использовать Invoke (и InvokeRequired), чтобы запустить метод обратно в потоке графического интерфейса. См. здесь .

51
ответ дан 28 November 2019 в 22:57
поделиться

Резьба не требуется. Используйте Application.DoEvents (); // перерисовываем или отвечаем на msg Например:

foreach (DirectoryInfo subDir in dirInfo.EnumerateDirectories())
{
    count = count + 1;
    listBoxControl4.Items.Add(count.ToString() + ":" + subDir.FullName);
    Application.DoEvents(); //allow repaint to see status
    ProduceListing(subDir, " ");
}

Это рекурсивно перебирает все папки и записывает имена в список. Это может занять много времени. С помощью DoEvents () он будет показывать прогресс в каждом цикле. По сути, вызов позволяет окнам в этом потоке обновлять что-либо в цикле windows msg. Обязательно следите за непреднамеренной рекурсией, поскольку любой элемент управления в форме может быть нажат еще раз, даже если ваш первый еще не завершен. Это хорошо работает. (Это копия старого вызова Delphi Application.ProcessMessages (). Вы можете найти его, чтобы узнать, почему он работает и на что обращать внимание.

-1
ответ дан 19 July 2019 в 09:51
поделиться

Очевидно , вам нужно использовать фоновые потоки. Предлагаю вам прочитать эту бесплатную электронную книгу .

0
ответ дан 28 November 2019 в 22:57
поделиться
    private voidForm_Load(object sender, EventArgs e)
    {
        MethodInvoker mk = delegate
        {
            //your job
        };
        mk.BeginInvoke(callbackfunction, null);
    }

    private void callbackfunction(IAsyncResult res)
    {
        // it will be called when your job finishes.
    }

использовать MethodInvoker - самый простой способ.

5
ответ дан 28 November 2019 в 22:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: