Подтвердить что ты не робот

WinForm Application UI зависает во время длительной работы

У меня есть приложение для форм Windows на котором мне нужно использовать цикл for, имеющий большое количество удаленных вызовов около 2000 - 3000 вызовов,

и, выполняя цикл for, я теряю контроль над элементами формы и формы, поскольку это становится большим процессом, и некоторое время он показывает "Не реагировать", но если я жду долго, он возвращается снова, я думаю, что я нужно использовать некоторую модель потоковой передачи для этого, есть ли какая-то идея, как я могу приступить к решению проблемы?

4b9b3361

Ответ 1

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

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

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

    ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
    

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

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

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

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

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

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

Ответ 2

    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.
    }

use MethodInvoker - самый простой способ.

Ответ 4

Ничего не нужно. Используйте Application.DoEvents(); //repaint or respond to 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(). Вы можете найти это, чтобы понять, почему он работает и что нужно отслеживать.