2009-07-20 3 views
2

немного несовершеннолетних вопроса ...Winforms выполнение кода в отдельном потоке

Я понимаю, что в приложении Winforms, долго выполняющийся код должен быть выполнен в отдельном потоке. Как это можно сделать, например, событие нажатия кнопки?

Я хочу сделать это, чтобы освободить поток пользовательского интерфейса, чтобы я мог одновременно накладывать текущую форму на полупрозрачную форму модального диалога. Я создал форму модального диалога с аккуратным загрузочным GIF, расположенным в центре, который отлично работает на событии нажатия кнопки самостоятельно.

Причина, по которой я выбрал этот метод, заключается в следующем: (1) Я хочу заблокировать любое взаимодействие пользователя с формой во время выполнения кода и (2) предоставить пользователю указание, что обработка выполняется (Я не знаю, как судить о том, как долго будет выполняться конкретный кусок кода, следовательно, выбор неопределенного индикатора загрузки gif).

Кроме того, по теме выполнения кода в отдельных потоках ... должно ли это не относиться к любому коду или только к долгосрочному коду?

Я бы очень признателен за любую помощь по этому вопросу! Спасибо!

ответ

8

Одним из простейших способов является использование компонента BackgroundWorker. Добавьте BackgroundWorker в свою форму, добавьте обработчик событий для события DoWork и вызовите оттуда долговременную функцию. Вы можете запустить его в обработчике событий нажатия кнопки, вызвав метод RunWorkerAsync на компоненте BackgroundWorker.

Чтобы узнать, когда операция готова, настройте обработчик для события RunWorkerCompleted.

private void Button_Click(object sender, EventArgs e) 
{ 
    myBackgroundWorker.RunWorkerAsync(); 
} 

private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // long-running operation here; will execute on separate thread 
} 

private void myBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // operation is ready 
} 
+0

Спасибо Fredrik. Я полагаю, если бы у вас было две длительные операции, которые можно было бы вызвать с одной из двух кнопок (щелчок), тогда вам нужно будет добавить 2 компонента BackgroundWorker в вашу форму ... да? – Shalan

+0

@Shalan: это был бы самый простой подход, да. –

+0

Спасибо, Fredrik – Shalan

3

Я отвечу на вторую половину вашего вопроса (как Fredrik уже объяснил BackgroundWorker):

Нет, это не имеет смысла, чтобы переместить задачу в отдельном потоке, если задача не является долгое время.

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

Как и любая техника программирования, вам необходимо взвесить затраты и выгоды для конкретной ситуации.

+0

Спасибо, Андрей. Это действительно солидный совет ... Я обязательно запомню это! – Shalan

2

Я попытаюсь ответить на вторую часть вашего вопроса, основываясь на собственном опыте. Вы обычно только использовать потоки в один из трех обстоятельств:

  • На операции, которые будут блокировать для заметных периодов времени на системных вызовов (File/Socket IO и т.д.)

  • На длительных операций, в которых потеря реакции пользовательского интерфейса нежелательна.

  • С несколькими длительными работами, где желательно использовать многоядерную среду.

Как говорит Эндрю Шеферд, есть накладные расходы для использования Threads. Нитки сильно осложняют ситуацию. Никогда не пронизывайте нить.

+0

Спасибо вам, Ник. И ваш, и совет Эндрю действительно проницательны, и заставляет меня переоценить, как я структурирую свой код. Хотя, что истолковано как долгое время? Есть ли эталонный тест, чтобы судить об этом. Я имею в виду, я мог бы развиваться на абсолютном осле машины, по сравнению с пользователем того же приложения, которое могло бы иметь молниеносный ПК. Совет?? – Shalan

+0

@Shalan: Я обычно определял бы длительную работу с точки зрения вычислительной сложности. Я бы сказал, что есть хороший случай для использования потоков всякий раз, когда у вас есть несколько вычислений, которые могут быть вычислены параллельно, при условии, что каждый из них будет запускать массивы данных разумного размера в полиномиальное время (или медленнее). Другой случай - с операциями ввода-вывода (особенно сокетов ввода-вывода), к которым я предлагаю, чтобы все, что может быть логически отложено и выполняться асинхронно, должно быть. Не работайте слишком сложно, чтобы найти применение для потоков. Идеальные кандидаты на резьбу часто становятся ясными при разработке вашего программного обеспечения. – Nick

+0

спасибо за ваш вклад, Ник! – Shalan

Смежные вопросы