Solved

VB.net Backgroundworker while quering

Posted on 2014-03-27
12
1,145 Views
Last Modified: 2014-04-03
I have a basic VB form that has a ListBox that is populated with the results from y WMI query of Programs.

The query takes longer than most of the WMI queries and my form is locked.
I know I can use BackgroundWorker Dowork, but I am not having any success with the collection results being passed into the Listbox and having a progress bar scroll while the process is doing work.

Imports System.Management
Imports System.DirectoryServices
Imports System.Net
Imports System.Net.OpenReadCompletedEventArgs
Imports System.Text
Imports System.Data
Imports System.ComponentModel

Public Class Form3
    Public Property ServerName() As String
        Get
            Return Me.Text
        End Get
        Set(ByVal Value As String)
            Me.Text = Value
        End Set
    End Property
    Private Sub Installed_Programs(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' Label2.Text = [String].Empty
        BGWForm3.RunWorkerAsync()


    End Sub

    Private Sub Collect_Programs()
        Dim scope = New ManagementScope("\\" & Me.Text & "\root\cimv2")


        scope.Connect()

        Dim query As ObjectQuery
        query = New ObjectQuery("Select * from Win32_Product")
        Dim searcher As ManagementObjectSearcher
        searcher = New ManagementObjectSearcher(scope, query)
        Dim queryCollection As ManagementObjectCollection
        queryCollection = searcher.Get()

        Dim m As ManagementObject



        For Each m In queryCollection

            If m("name") Is Nothing Then
            Else

                ListBox1.Items.Add(m("name"))




            End If

        Next
    End Sub

    Private Sub BGWForm3_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BGWForm3.DoWork

        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        'Dim i As Integer


        If (worker.CancellationPending = True) Then
            e.Cancel = True
            'Exit For
        Else
            Collect_Programs()
            'Perform a time consuming operation and report progress.
            'System.Threading.Thread.Sleep(500)
            'worker.ReportProgress(i * 10)

        End If

    End Sub

    ' This event handler updates the progress. 
    'Private Sub backgroundWorker1_ProgressChanged(ByVal sender As System.Object, _
    'ByVal e As ProgressChangedEventArgs) Handles BGWForm3.ProgressChanged
    '    'resultLabel.Text = (e.ProgressPercentage.ToString() + "%")
    '    ToolStripProgressBar1.Value = e.ProgressPercentage
    'End Sub

    ' This event handler deals with the results of the background operation. 
    Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles BGWForm3.RunWorkerCompleted
        If e.Cancelled = True Then
            'resultLabel.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            'resultLabel.Text = "Error: " & e.Error.Message
        Else
            'resultLabel.Text = "Done!"
            'ToolStripProgressBar1.Style.Blocks()
        End If
    End Sub



    Private Sub BGWForm3_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles BGWForm3.ProgressChanged
        'Me.ProgressBar1.Value = e.ProgressPercentage
        ToolStripProgressBar1.Style = ProgressBarStyle.Marquee
        ToolStripProgressBar1.MarqueeAnimationSpeed = 50
        ToolStripProgressBar1.Value = e.ProgressPercentage
        'ListBox1.Items.Add(e.)
    End Sub


End Class

Open in new window

0
Comment
Question by:yo_bee
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 2
  • 2
  • +1
12 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39960248
The problem I think you are having--you didn't specify whether or not you were encountering errors--is that you are trying to update UI controls from separate threads. UI controls can only be updated from the thread on which they were created. In order to update across threads, you have to use the Invoke pattern. See my comment here:

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_28305300.html#a39681287

...for a function that will let you interact with controls across threads. That example is for reading, but you can easily change it to writing instead. There is nothing special to do other than call the function.

The alternative, and probably more preferable way, would be to work with the ProgressChanged event.
0
 
LVL 23

Author Comment

by:yo_bee
ID: 39960283
What if I just want the ProgressBar scroll Marque Style while the Query is running then when the query is complete the LISTBOX will be populated.

Is that possible without having a cross-thread?
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 39960295
A PB is still a UI control, so you will have the same issue.
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 23

Author Comment

by:yo_bee
ID: 39960311
Here is the errorCross-thread
0
 
LVL 83

Expert Comment

by:CodeCruiser
ID: 39961243
One way to accomplish this would be to declare queryCollection at class level. Then move the following code

        For Each m In queryCollection

            If m("name") Is Nothing Then
            Else

                ListBox1.Items.Add(m("name"))




            End If

        Next

Open in new window



out of Collect_Programs method and into backgroundWorker1_RunWorkerCompleted method.
0
 
LVL 23

Author Comment

by:yo_bee
ID: 39961287
Sorry, but I am a novice when it comes to some of these methods and what your saying I am not sure how to do.
0
 
LVL 83

Assisted Solution

by:CodeCruiser
CodeCruiser earned 100 total points
ID: 39961290
I pointed out the steps but here those are again

1) Move
Dim queryCollection As ManagementObjectCollection

line out of Collect_Programs to just under your

Public Class Form3

line.

2) Move the code shown above out of the Collect_Programs and into RunWorkerCompleted method.
0
 
LVL 23

Author Comment

by:yo_bee
ID: 39963997
@CodeCrusier

Thanks for the suggestion.
It partially worked.
The form still is locked up during the process.

What I would like is to either have a progressbar scroll while the data is being collected and once complete populate the Listview (I made a change from ListBox to a ListView)
0
 
LVL 28

Assisted Solution

by:Ark
Ark earned 400 total points
ID: 39968740
You can fill ListBox in BGWForm3_ProgressChanged event handler. Use UserState property to pass name:
    Private Sub Collect_Programs(ByVal worker As BackgroundWorker)
'skipped
        Dim i, count, percents As Integer
        count = queryCollection.Count
        For Each m In queryCollection
            i+=1
            If m("name") Is Nothing Then
            Else
                percents = i*100/count
                worker.ReportProgress(i, m("name"))
            End If

        Next
    End Sub

    Private Sub BGWForm3_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BGWForm3.DoWork

        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        If (worker.CancellationPending = True) Then
            e.Cancel = True
        Else
            Collect_Programs(worker)
        End If

    End Sub

    Private Sub BGWForm3_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles BGWForm3.ProgressChanged
        ToolStripProgressBar1.Value = e.ProgressPercentage
        ListBox1.Items.Add(e.UserState.ToString)
    End Sub

Open in new window

0
 
LVL 23

Author Comment

by:yo_bee
ID: 39969321
What if I changed the Listbox1 to ListView1 and the Listview has two columns?

        For Each m In queryCollection

            If m("name") Is Nothing Then
            Else

                Dim LVI As New ListViewItem
                LVI.Text = m("name")
                LVI.SubItems.Add(m("Version"))
                ' bw.ReportProgress(i)

                ListView1.Items.Add(LVI)
                ListView1.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent)
                ListView1.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent)
                ''ListBox1.Items.Add(m("name"))

            End If

        Next

Open in new window

0
 
LVL 28

Accepted Solution

by:
Ark earned 400 total points
ID: 39974206
You can't call UI items (form controls) from another thread. But you can post any object accross threads via ReportProgress:
   For Each m In queryCollection

            If m("name") Is Nothing Then
            Else
                bw.ReportProgress(i, m)
            End If

        Next
   Private Sub BGWForm3_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles BGWForm3.ProgressChanged
        ToolStripProgressBar1.Value = e.ProgressPercentage
        Dim m = e.UserState
        Dim LVI As New ListViewItem
        LVI.Text = m("name")
        LVI.SubItems.Add(m("Version"))
        ListView1.Items.Add(LVI)
        ListView1.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent)
        ListView1.AutoResizeColumn(1, ColumnHeaderAutoResizeStyle.ColumnContent)
  End Sub

Open in new window

0
 
LVL 23

Author Closing Comment

by:yo_bee
ID: 39974722
I want to thank everyone for their suggestions.
This one is a tough one for me to wrap my head around.
I tried to follow http://www.codeproject.com/Articles/93260/Retrieving-Information-From-Windows-Management-Ins, but I had trouble understanding the Delegates .

Thanks
ARK.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you find yourself in this situation “I have used SELECT DISTINCT but I’m getting duplicates” then I'm sorry to say you are using the wrong SQL technique as it only does one thing which is: produces whole rows that are unique. If the results you a…
This article describes how to use the timestamp of existing data in a database to allow Tableau to calculate the prior work day instead of relying on case statements or if statements to calculate the days of the week.
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

634 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question