vb.net and using a background worker

I developed a program that uses WMI to retrieve processes running on a remote workstation.  The problem is it takes about 15 seconds to fully load everything.  My solution is running that method in a background thread so that the user GUI isnt completely frozen making it look like my app is broke.  I am using the below code to run this in the background worker.  ( The example i am using from http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx works fine).  I get an error with the below code (Cross-thread operation not valid: Control 'ListView1' accessed from a thread other than the thread it was created on.)

Imports System.ComponentModel
Imports System.Management

Public Class Form1
    Private bw As BackgroundWorker = New BackgroundWorker


    Public Sub New()
        InitializeComponent()
        bw.WorkerReportsProgress = True
        bw.WorkerSupportsCancellation = True
        AddHandler bw.DoWork, AddressOf BackgroundWorker1_DoWork
        AddHandler bw.ProgressChanged, AddressOf BackgroundWorker1_ProgressChanged
        AddHandler bw.RunWorkerCompleted, AddressOf BackgroundWorker1_RunWorkerCompleted

    End Sub


    Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        'For i = 1 To 10
        'If bw.CancellationPending = True Then
        '    e.Cancel = True
        '    Exit For
        'Else
        ' Perform a time consuming operation and report progress.
        'System.Threading.Thread.Sleep(500)
        'bw.ReportProgress(i * 10)
        Dim RC As String = "10.243.12.139"
        
            ListView1.Items.Clear()

            Dim theScope As New ManagementScope("\\" & RC & "\root\cimv2")
            Dim objectQuery As New ObjectQuery("SELECT * FROM Win32_Process")
            ListView1.Groups.Add(New ListViewGroup("Processes", "Process List"))
            For Each managementObject As ManagementObject In (New ManagementObjectSearcher(theScope, objectQuery)).[Get]()
                Dim item As ListViewItem = ListView1.Items.Add(managementObject("Name").ToString())
                item.SubItems.Add(managementObject("ProcessId").ToString())
                item.Group = ListView1.Groups("Processes")
            Next
                'End If
        'Next

    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        Me.tbProgress.Text = e.ProgressPercentage.ToString() & "%"

    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        If e.Cancelled = True Then
            Me.tbProgress.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            Me.tbProgress.Text = "Error: " & e.Error.Message
        Else
            Me.tbProgress.Text = "Done!"
        End If

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not bw.IsBusy = True Then
            bw.RunWorkerAsync()
        End If

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        If bw.WorkerSupportsCancellation = True Then
            bw.CancelAsync()
        End If
    End Sub
End Class

Open in new window

derek7467Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Guy Hengel [angelIII / a3]Billing EngineerCommented:
I had the same issue. problem is indeed that the background worker process will not have access to any of the visual controls (by that error message)
the solution I had implemented is that the background worker process fills the data into some variable of the form (for example some collection...), and when done (in the event) requests the form to refresh from that collection.
0
it_saigeDeveloperCommented:
Actually there is a really simple solution to this issue.  Use the background workers report progress to update the listview.
Imports System.ComponentModel
Imports System.Linq
Imports System.Management

Public Class Form1
	Private bw As BackgroundWorker = New BackgroundWorker

	Public Sub New()
		InitializeComponent()
		bw.WorkerReportsProgress = True
		bw.WorkerSupportsCancellation = True
		AddHandler bw.DoWork, AddressOf OnDoWork
		AddHandler bw.ProgressChanged, AddressOf OnProgressChanged
		AddHandler bw.RunWorkerCompleted, AddressOf OnWorkerCompleted
	End Sub

	Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
		If Not bw.IsBusy = True Then
			ListView1.Items.Clear()
			ListView1.Groups.Add(New ListViewGroup("Processes", "Process List"))
			ListView1.Groups.Add(New ListViewGroup("Sandwiches", "Sandwich List"))
			bw.RunWorkerAsync()
		End If
	End Sub

	Private Sub OnDoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
		Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
		Dim RC As String = "10.243.12.139"

		Dim theScope As New ManagementScope(String.Format("\\{0}\root\cimv2", RC))
		Dim objectQuery As New ObjectQuery("SELECT * FROM Win32_Process")
		For Each managementObject As ManagementObject In (New ManagementObjectSearcher(theScope, objectQuery)).[Get]()
			Dim item As New ListViewItem(managementObject("Name").ToString())
			item.SubItems.Add(managementObject("ProcessId").ToString())
			worker.ReportProgress(0, New ListViewState() With {.Item = item, .Group = ListViewGroupDefinition.Processes})
		Next
		worker.ReportProgress(0, New ListViewState() With {.Item = New ListViewItem("Ham"), .Group = ListViewGroupDefinition.Sandwiches})
		worker.ReportProgress(0, New ListViewState() With {.Item = New ListViewItem("Salami"), .Group = ListViewGroupDefinition.Sandwiches})
		worker.ReportProgress(0, New ListViewState() With {.Item = New ListViewItem("Turkey"), .Group = ListViewGroupDefinition.Sandwiches})
		'End If
		'Next

	End Sub

	Private Sub OnProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
		Me.tbProgress.Text = e.ProgressPercentage.ToString() & "%"
		If Not e.UserState Is Nothing AndAlso TypeOf e.UserState Is ListViewState Then
			Dim state As ListViewState = TryCast(e.UserState, ListViewState)
			If Not state Is Nothing Then
				Select Case state.Group
					Case ListViewGroupDefinition.None
						Exit Select
					Case ListViewGroupDefinition.Processes
						state.Item.Group = ListView1.Groups("Processes")
						Exit Select
					Case ListViewGroupDefinition.Sandwiches
						state.Item.Group = ListView1.Groups("Sandwiches")
						Exit Select
				End Select
				ListView1.Items.Add(state.Item)
			End If
		End If
	End Sub

	Private Sub OnWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
		If e.Cancelled = True Then
			Me.tbProgress.Text = "Canceled!"
		ElseIf e.Error IsNot Nothing Then
			Me.tbProgress.Text = "Error: " & e.Error.Message
		Else
			Me.tbProgress.Text = "Done!"
		End If
	End Sub
End Class

Public Class ListViewState
	Public Property Item() As ListViewItem
	Public Property Group As ListViewGroupDefinition
End Class

Public Enum ListViewGroupDefinition As Integer
	None = 0
	Processes = 1
	Sandwiches = 2
End Enum

Open in new window


-saige-
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
derek7467Author Commented:
AWESOME!!!!!! Thank you!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.