【问题标题】:Running class as new thread将类作为新线程运行
【发布时间】:2009-03-05 09:36:47
【问题描述】:

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

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

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

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

谢谢。

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

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

【问题讨论】:

    标签: c# vb.net backgroundworker


    【解决方案1】:

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

    否则,您可以使用您提到的BackgroundWorker。 MSDN 页面有一个示例。

    编辑:短篇小说是:

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

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

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

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

    【讨论】:

    • 我正在使用 webservices 和 MTOM 从服务器获取大文件,所以我无法使用 WebClient。
    • 在这种情况下,在您的服务引用上生成异步方法并使用这些方法。
    • @inferis - 网络服务上的异步方法不会提供进度通知。
    • 是的。此外,他已经有一堂课了,所以BGW 是要走的路。
    • 我的班级循环读取文件块,直到下载整个文件。在读取每个块后,我都会引发一个 DownloadedBytes 事件。现在,如何使用backgroundworker,我真的不明白在哪里使用它,在调用者或下载类中。
    【解决方案2】:

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

    【讨论】:

    【解决方案3】:

    我创建了几个包含 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
    

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      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
      

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

      【讨论】:

      • 我建议不要使用 WaitCallback,因为将事件返回到 UI 线程更困难(我认为这是他想要完成的事情)。
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 2016-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-07
        • 2023-03-25
        • 2014-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多