Разница между BeginInvoke и Thread.Start - PullRequest
20 голосов
/ 04 августа 2009

У меня есть диалоговое приложение, в котором я делегирую операцию ввода-вывода для чтения и записи в другой поток.

Я просто хочу уточнить, есть ли разница между двумя подходами ..

Первый подход: (я делаю это в моей основной форме -Form.cs)

delegate void Action();
Action _action = new Action(Method);
this.BeginInvoke(_action);

Второй подход:

Thread th = new  Thread( new ThreadStart(_action));
th.Start();

Я заметил, что BeginInvoke зависает на секунду, а второй - нет ..

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

Ответы [ 6 ]

17 голосов
/ 04 августа 2009

BeginInvoke опубликует действие в очереди сообщений насоса сообщений в том же потоке, что и Form, оно не создаст новый поток.

Control.BeginInvoke ведет себя подобно асинхронному запуску потока, но имеет важные внутренние различия.

Подробнее читайте статью здесь .

8 голосов
/ 04 августа 2009

BeginInvokes выполняет делегат асинхронно в потоке пользовательского интерфейса (именно поэтому он вешает пользовательский интерфейс), отправляя сообщение в окно. Это то, что вам нужно сделать, если код в делегате обращается к пользовательскому интерфейсу.

Подход с Thread.Start выполняет делегаты в новом, независимом потоке.

3 голосов
/ 04 августа 2009

Попробуйте это.

class Form1: Form
{
   public void ButtonWasClicked(object sender, EventArgs e)
   {
       /* Call the UI's 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 () не всегда ваше лучшее решение. Попробуйте _abort flags в вашем коде процесса и заблокируйте его.

Надеюсь, я ответил на вопрос.

Лев Бруццанити

3 голосов
/ 04 августа 2009

Thread.Start запускает его на вашем новом Thread.

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

1 голос
/ 04 августа 2009

Как уже сообщали другие, Thread.Start запустит новый поток, а Control.BeginInvoke () запустит код в потоке пользовательского интерфейса (например, если вы хотите изменить значение поля).

Однако я обнаружил, что самый простой метод выполнения фоновой задачи в WinForms - это использование BackgroundWorker . Вы помещаете его в форму, связываете события и вызываете RunWorkerAsync (). Затем вы пишете фоновую задачу в событии DoWork. Любое обновление пользовательского интерфейса может быть помещено в событие RunWorkerCompleted.

Использование BackgroundWorker позволяет избежать всей надоедливой обработки потоков и вещей IsInvokeRequired.

Вот более подробная статья с инструкциями .

0 голосов
/ 04 августа 2009

разница будет в том, что метод BeginInvoke просто вызывает делегат асинхронно в одном и том же потоке.

Используя Thread.Start, вы создадите совершенно другой поток.

Thread.Start определенно даст вам лучшую производительность!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...