Разница между BeginInvoke и Thread.Start
У меня есть приложение на основе диалога, в котором я буду делегировать операцию ввода-вывода для чтения в другой поток.
Я просто хочу прояснить, есть ли разница между двумя подходами.
Первый подход: (Я делаю это, моя основная форма -Form.cs)
delegate void Action();
Action _action = new Action(Method);
this.BeginInvoke(_action);
Второй подход:
Thread th = new Thread( new ThreadStart(_action));
th.Start();
Я заметил, что BeginInvoke навевает интерфейс на второй, а второй подход не делает.
Пожалуйста, помогите
Ответы
Ответ 1
BeginInvoke
опубликует действие в очереди сообщений насоса сообщений в том же потоке, что и Form
, он не создаст новый поток.
Control.BeginInvoke
ведет себя аналогично началу асинхронного потока, но имеет важные внутренние различия.
Прочтите более подробно статью здесь.
Ответ 2
BeginInvokes выполняет асинхронный перевод делегата в потоке пользовательского интерфейса (который вызывает зависание интерфейса), отправляя сообщение в окно. Это то, что вам нужно сделать, если код в делегате обращается к пользовательскому интерфейсу.
Подход с Thread.Start выполняет делегаты в новом независимом потоке.
Ответ 3
Thread.Start
запускает его на вашем новом Thread
.
Control.BeginInvoke
запускает метод в потоке, которому принадлежит элемент управления. Если вы в данный момент находитесь в потоке элемента управления, метод не запускается до тех пор, пока вы не вернете управление в цикл сообщения, например. выйдите из обработчика событий.
Ответ 4
Попробуйте это.
class Form1: Form
{
public void ButtonWasClicked(object sender, EventArgs e)
{
/* Call the UI Invoke() method */
this.Invoke((MethodInvoker)delegate()
{
/* Stuff to do.. you can access UI elements too without
* the nasty "Control accessed from another thread.."
* Use BeginInvoke() only if you have code after this section
* that you want the UI to execute without waiting for this
* inner blockto finish.
*/
});
}
}
В отношении BeginInvoke() он используется, поэтому функция будет немедленно возвращаться, и следующая строка будет выполнена и так далее и т.д., не дожидаясь завершения метода.
Разница в том, что если вы создаете поток, у вас будет больше контроля над ним, как и любой другой поток. Вы столкнетесь с CrossThreadExceptions! Если вы используете IAsyncResult и BeginInvoke(), у вас не будет контроля над потоком выполнения асинхронной операции, поскольку она управляется средой выполнения.
С вызовом вы также можете отправить больше параметров методу и вызвать метод, который вызывается после завершения операции.
MyDelegateWithTwoParam del = new MyDelegateWithTwoParam(_method);
AsyncCallback callback = new AsyncCallback(_callbackMethod);
IAsyncResult res = del.BeginInvoke(param1, param2, callback, null);
private void _callbackMethod(IAsyncResult iar) {
/* In this method you can collect data that your operation might have returned.
* If MyDelegateWithTwoParam has a return type, you can find out here what i was. */
}
Я широко использовал оба для разработки пользовательского интерфейса. Я бы использовал потоки больше для сервис-подобных объектов. (Подумайте о объекте, который остается и прослушивает TCP-соединения) и асинхронные методы фоновой работы за пользовательским интерфейсом (посмотрите также на BackgroundWorker).
Не волнуйтесь, если первый подход занял дополнительную секунду, чтобы начать: Thread.Abort() не
всегда ваше лучшее решение. Попробуйте _баборить флаги в коде процесса и заблокировать его.
Надеюсь, я ответил на вопрос.
Лео Бруццанити
Ответ 5
Как уже отмечали другие, Thread.Start запустит новый поток, а Control.BeginInvoke() запустит код в потоке пользовательского интерфейса (обязательно, если вы хотите изменить значение поля, например).
Однако я обнаружил, что самый простой способ выполнения фоновой задачи в WinForms - использовать BackgroundWorker. Вы бросаете его на форму, подключаете события и вызываете RunWorkerAsync(). Затем вы записываете фоновое задание в событие DoWork. Любое обновление пользовательского интерфейса может быть помещено в событие RunWorkerCompleted.
Использование BackgroundWorker позволяет избежать всех раздражающих потоков обработки и IsInvokeRequired.
Вот более подробная справочная статья.
Ответ 6
разница заключалась бы в том, что метод BeginInvoke просто вызывает делегат асинхронно в SAME-потоке.
Используя Thread.Start, вы создадите совершенно другой поток.
Thread.Start определенно даст вам лучшую производительность!