Solved

VB.net Backgroundworker while quering

Posted on 2014-03-27
12
1,046 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
  • 6
  • 2
  • 2
  • +1
12 Comments
 
LVL 74

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 21

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 74

Expert Comment

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

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 21

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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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 21

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 27

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 21

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 27

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 21

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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Microsoft Reports are based on a report definition, which is an XML file that describes data and layout for the report, with a different extension. You can create a client-side report definition language (*.rdlc) file with Visual Studio, and build g…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

708 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now