2017-05-29 2 views
0

Je cours un BackgroundWorker et je souhaite signaler sa progression. Dans l'exemple ci-dessous, je crée une liste de tests que BackgroundWorker parcourt ensuite. Le problème réside dans la ligne 'sender.ReportProgress (i)'. Si j'ai Option Strict sur, il n'aime pas mon utilisation de 'i' en raison de problèmes de liaison tardive. Existe-t-il un autre moyen de coder ceci et d'éviter ce problème?Problème de liaison tardive avec BackgroundWorker dans VB.Net

Public Class Form1 

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load 
     ' Configuring for Background Workers 
     Control.CheckForIllegalCrossThreadCalls = False 

     Dim MyList As New List(Of String) 
     For a As Integer = 0 To 100 
      MyList.Add(CStr(a)) 
     Next 
    End Sub 

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
     Dim bgw As New System.ComponentModel.BackgroundWorker 
     bgw.WorkerReportsProgress = True 
     bgw.WorkerSupportsCancellation = True 
     AddHandler bgw.DoWork, AddressOf bgw_DoWork 
     ' I create a BackgroundWorker here rather than add one in the toolbox so that I can specify the Handler and use different Handler routines for different part of a large program. 

     Button1.Enabled = False 
     Dim progress As New Progress(bgw) 
     progress.ShowDialog() 
     Button1.Enabled = True 
    End Sub 

    Private Sub bgw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) 
     For i = 0 To MyList.Count -1 
      Label1.Text = MyList(i) 
      sender.ReportProgress(i) 
      System.Threading.Thread.Sleep(200) 
      Label1.Refresh() 
     Next 

    End Sub 

End Class 


Public Class Progress 
    Private WithEvents _BGW As System.ComponentModel.BackgroundWorker 

    Public Sub New(ByVal BGW As System.ComponentModel.BackgroundWorker) 
     _BGW = BGW 
     InitializeComponent() 
    End Sub 

    Private Sub frmProgress_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown 
     If Not IsNothing(_BGW) Then 
      _BGW.RunWorkerAsync() 
     End If 
    End Sub 

    Private Sub _BGW_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles _BGW.ProgressChanged 
     ProgressBar1.Value = e.ProgressPercentage 
     Label1.Text = e.ProgressPercentage 
    End Sub 

    Private Sub _BGW_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles _BGW.RunWorkerCompleted 
     Me.Close() 
    End Sub 
End Class 
+0

Ce n'est pas le 'i 'avec lequel il y a un problème, c'est la méthode' ReportProgress' - 'System.Object' n'a pas une telle méthode. Il y a plusieurs autres problèmes. D'un côté, vous devriez visiter la page [tour] - vos 3 derniers posts ont 5 réponses mais tous restent ouverts car aucune réponse n'a été acceptée, – Plutonix

+0

Merci pour vos commentaires. Quels sont les autres problèmes? OK à propos de l'acceptation - je n'avais pas réalisé que j'étais censé le faire. –

Répondre

1
CType(sender, BackgroundWorker).ReportProgress(i) 
+0

Juste une petite note: Il est préférable (et plus rapide) d'utiliser [** 'DirectCast' **] (https://docs.microsoft.com/en-us/dotnet/articles/visual-basic/language-reference/opérateurs/directcast-operator) lorsque le type d'objet est connu. 'CType' est supposé être utilisé lors de la conversion en un type _ ** différent ** _ (par exemple convertir un' Byte' en un 'Integer', bien que cela soit généralement fait implicitement quand on n'utilise pas' Option Strict'). –

+0

La différence entre les deux est que 'CType' essaie d'utiliser [** les opérateurs de conversion **] (https://docs.microsoft.com/en-us/dotnet/articles/visual-basic/programming-guide/language -features/procedures/how-to-define-a-conversion-operator) pour effectuer une conversion, et si cela échoue, il va essayer de lancer à la place. 'DirectCast' ne fait que transtyper et est donc beaucoup plus rapide que' CType' quand vous ne cherchez pas à convertir un objet en un type différent. –

1

Aussi, si vous voulez faire plusieurs actions avec, puis créer une variable de référence locale comme ceci:

Private Sub bgw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) 

    Dim bgw As System.ComponentModel.BackgroundWorker = DirectCast(sender, System.ComponentModel.BackgroundWorker) 

    ' ... now you can use "bgw" multiple times below instead of casting each time ... 

    For i = 0 To MyList.Count -1 
     Label1.Text = MyList(i) 
     bgw.ReportProgress(i) 
     bgw.SomethingElse() 
     bgw.MoreStuff() 
     System.Threading.Thread.Sleep(200) 
     Label1.Refresh() 
    Next 
End Sub 

Il est évident que ce n'est pas nécessaire dans votre cas, juste un FYI ...