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

Разница между 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 навевает интерфейс на второй, а второй подход не делает.

Пожалуйста, помогите

4b9b3361

Ответ 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 определенно даст вам лучшую производительность!