Solved

VB.net Backgroundworker while quering

Posted on 2014-03-27
12
1,124 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
Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

 
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

MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

Question has a verified solution.

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

'Between' is such a common word we rarely think about it but in SQL it has a very specific definition we should be aware of. While most database vendors will have their own unique phrases to describe it (see references at end) the concept in common …
If you have heard of RFC822 date formats, they can be quite a challenge in SQL Server. RFC822 is an Internet standard format for email message headers, including all dates within those headers. The RFC822 protocols are available in detail at:   ht…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
This video shows how to use Hyena, from SystemTools Software, to update 100 user accounts from an external text file. View in 1080p for best video quality.

734 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