Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

vb.net and using a background worker

Posted on 2014-11-06
3
Medium Priority
?
609 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
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 35

Accepted Solution

by:
it_saige earned 2000 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

Technology Partners: 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

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

886 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