4

我想在一个新线程中开始工作或使用后台工作人员来做这件事,但之前没有做过,并问你我应该怎么做。

我的程序有一个带有文件列表的datagridview,每行一个文件。我希望用户能够选择一行,然后按“开始下载”开始下载的后台作业。我想获取有关下载进度的事件。

我有一个类 clsDownload 可以处理所有事情并引发事件,但是如何实现后台工作?

我应该在类内部使用 System.ComponentModel.BackgroundWorker 还是创建一些处理此问题的包装器或使用其他一些线程的东西?

谢谢。

编辑:我不明白如何在后台实现我的下载,任何小例子都会很好。msdn 上的示例并没有让我走得太远。

我有一个具有 StartDownload 功能的下载类。我应该在课堂上还是在调用者中使用后台工作人员?“感觉很愚蠢”

4

5 回答 5

3

我你只做下载,不需要其他异步处理,你可以使用WebClient类的异步方法。虽然由于您已经拥有自己的课程,但这可能不是您的解决方案。

否则,您可以BackgroundWorker按照您提到的那样使用。MSDN 页面有一个示例如何执行此操作。

编辑:短篇小说是:

  • BackgroundWorker从调用者创建;
  • 当你想开始后台工作时,你调用BackgroundWorker.RunWorkerAsync;
  • DoWork事件处理程序中,您执行后台工作,在您的情况下,您开始下载类;
  • 当你在做后台工作时,你必须每隔一段时间检查一次CancelationPending
  • 当您想报告一些进度时,您需要以百分比计算并调用ReportProgress.

如果您需要真正定制的东西,您可以随时创建自己的Thread.

我个人会坚持BackgroundWorker。它为工作的各个阶段提供了一组很好的通知。如果您使用Thread,则必须自己实现这些。

我还会确保代码不会创建太多实例。您想限制并发下载的数量并将超过该数量的任何内容排队。

于 2009-03-05T09:50:58.453 回答
3

BackgroundWorker如果您需要在 UI 上向用户提供反馈,我强烈建议您。和事件在 UI 线程上运行ProgressChangedRunWorkerCompleted因此无需进行编组,这会使您的代码更加复杂。

于 2009-03-05T09:55:42.950 回答
1

我创建了几个包含 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 关键字。从这些处理程序中,您可以调用 BackgroundWorker 的 ReportProgress 方法。在 ReportProgress 中,您可以对 UI 进行任何更改以指示进度。这是一个例子:

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

希望这可以帮助。

于 2009-03-05T17:43:09.410 回答
0

backgroundworker 看起来应该可以工作... 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

取决于线程需要哪些参数。

于 2009-03-05T09:50:08.500 回答
0

使用 clsDownload 的类(可能是您的 Form 类)应该使用 BackgroundWorker 来运行下载方法。

于 2009-03-05T17:52:11.680 回答