Solved

vb.net and using a background worker

Posted on 2014-11-06
3
519 Views
Last Modified: 2014-11-06
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

0
Comment
Question by:derek7467
[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
3 Comments
 
LVL 143

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 40425970
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
 
LVL 34

Accepted Solution

by:
it_saige earned 500 total points
ID: 40426317
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
 

Author Closing Comment

by:derek7467
ID: 40426516
AWESOME!!!!!! Thank you!
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

It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
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 …
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

738 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