Запуск класса как нового потока - PullRequest
4 голосов
/ 05 марта 2009

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

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

У меня есть класс clsDownload, который обрабатывает все и вызывает события обратно, но как мне реализовать фоновую обработку?

Должен ли я использовать System.ComponentModel.BackgroundWorker внутри класса, или создать какую-нибудь оболочку, которая обрабатывает это, или использовать какие-то другие потоки?

Спасибо.

Редактировать: Я не понимаю, как реализовать мою загрузку в фоновом режиме, любой маленький пример был бы очень хорош. Пример на MSDN не дал мне далеко.

У меня есть класс загрузки, который имеет функцию StartDownload. Должен ли я использовать фоновый работник в классе или в вызывающей программе? "чувствую себя глупо"

Ответы [ 5 ]

3 голосов
/ 05 марта 2009

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

В противном случае вы можете использовать BackgroundWorker, как вы упомянули. На странице MSDN есть пример, как это сделать.

РЕДАКТИРОВАТЬ: Короткая история:

  • Вы создаете BackgroundWorker из вызывающей стороны;
  • Если вы хотите начать фоновую работу, вы звоните BackgroundWorker.RunWorkerAsync;
  • в обработчике событий DoWork вы выполняете фоновую работу, в вашем случае вы запускаете класс загрузки;
  • пока вы выполняете фоновую работу, вам нужно время от времени проверять наличие CancelationPending;
  • когда вы хотите сообщить о каком-либо прогрессе, вам нужно рассчитать его в процентах и ​​позвонить по номеру ReportProgress.

А если вам нужно что-то действительно настроенное, вы всегда можете создать свой собственный Thread.

Лично я бы придерживался BackgroundWorker. Имеет приятный набор уведомлений для разных этапов работы. Если вы используете Thread, вам придется реализовать их самостоятельно.

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

3 голосов
/ 05 марта 2009

Я бы настоятельно рекомендовал BackgroundWorker, если вам необходимо предоставить отзыв пользователю в пользовательском интерфейсе. События ProgressChanged и RunWorkerCompleted запускаются в потоке пользовательского интерфейса, поэтому нет необходимости выполнять маршалинг, который может сделать ваш код более сложным.

1 голос
/ 05 марта 2009

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

Вот как может выглядеть ваш класс работы:

Private m_bwMain As BackgroundWorker

Public Sub New(ByVal bwMain As BackgroundWorker)
    m_bwMain = bwMain

    'additional setup code here
End Sub

Чтобы начать работу, вы должны сделать что-то подобное в обработчике события Click вашей кнопки «Начать загрузку»:

lblStatus.Text = "Initializing ..."
bgwMain.RunWorkerAsync(someFileName)

Я объявляю свой класс задания как закрытый член текущей формы, а затем создаю его экземпляр в событии BackgroundWorker.DoWork. Оттуда вы можете вызвать свой метод для загрузки файла:

Private Sub bgwMain_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwMain.DoWork
    m_oJobEngine = New JobEngine(CType(sender, BackgroundWorker))
    m_oJobEngine.DownloadFile(CStr(e.Argument))
End Sub

Чтобы сообщить о прогрессе пользователю, вы можете обрабатывать события, вызванные вашим классом, в основной форме. Вам просто нужно убедиться, что объявление объекта класса задания имеет ключевое слово WithEvents. Из этих обработчиков вы можете вызвать метод ReportProgress в BackgroundWorker. Из ReportProgress вы можете вносить любые необходимые изменения в пользовательский интерфейс, чтобы показать прогресс. Вот пример:

Private Sub m_oJobEngine.DownloadProgress(ByVal bgw as Backgroundworker, ByVal bytesTransferred as Long) Handles m_oJobEngine.DownloadProgress
    bgw.ReportProgress(0, bytesTransferred)
End Sub
Private Sub bgwMain_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwMain.ProgressChanged
    lblStatus.Text = CLng(e.UserState).ToString & " bytes transferred."
End Sub

Надеюсь, это поможет.

0 голосов
/ 05 марта 2009

Класс, который использует clsDownload (вероятно, ваш класс Form), должен использовать BackgroundWorker для запуска метода загрузки.

0 голосов
/ 05 марта 2009

Фоновый работник выглядит так, как будто должно работать ... Есть пример на MSDN.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Или вы можете сделать что-то вроде:

WaitCallBack workCallBack= new WaitCallBack(DownloadMethod);
if(!ThreadPool.QueueUserWorkItem(workCallBack, "ThreadPooled")
{
   // Unable to Pool
}

// Work has been added to pool and will execute when possible

Зависит от того, какие параметры вам нужны для потока.

...