• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 383
  • Last Modified:

vb.net and background worker for system uptime

I am attempting to write a small amount of code to return to me the system uptime of a remote workstation.  It works when ran directly from a button, but when i try to put it in a background thread it fails everytime.

Below is the code i am using:

Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Try
            Dim str_ServerName As String = TextBox1.Text
            Dim pc As New PerformanceCounter("System", "System Up Time", "", str_ServerName)
            pc.NextValue()
            Dim ts As TimeSpan = TimeSpan.FromSeconds(pc.NextValue)
            MsgBox(str_ServerName & " has been up for " & ts.Days & " days, " & ts.Hours & " hours, " & ts.Minutes & " minutes, " & " and " & ts.Seconds & " seconds.", , "System Uptime")
        Catch ex As Exception
            MsgBox("Workstation Uptime not found", MsgBoxStyle.Information, "Information")
        End Try
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        If e.Cancelled = True Then
        End If
    End Sub

Open in new window


I declare the below:
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

Open in new window


I then try to run the method from a button:
  If Not bw.IsBusy = True Then
            bw.RunWorkerAsync()
        End If

Open in new window


What am i doing wrong?
0
derek7467
Asked:
derek7467
1 Solution
 
AndyAinscowCommented:
The background worker doesn't support UI - eg. MessageBox - elements.  You would need to pass the uptime back to the main thread to display the result.
0
 
derek7467Author Commented:
This is the error i get:

Cross-thread operation not valid: Control 'TextBox1' accessed from a thread other than the thread it was created on.
0
 
derek7467Author Commented:
How do i pass it back?
0
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 
derek7467Author Commented:
I supposed this would be bad coding to use the below???

TextBox.CheckForIllegalCrossThreadCalls = false
0
 
Kyle AbrahamsSenior .Net DeveloperCommented:
Use a BeginInvoke to bubble it up to the UI thread:
http://msdn.microsoft.com/en-us/library/a06c0dc2(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
Me.BeginInvoke(new Delegate(AddressOf showMsgBox),  str_ServerName & " has been up for " & ts.Days & " days, " & ts.Hours & " hours, " & ts.Minutes & " minutes, " & " and " & ts.Seconds & " seconds.", "System Uptime")

public sub showMessageBox(text as string, Caption as string)
 MsgBox(text, , Caption)
end sub

Open in new window

0
 
Michael O'SheaCommented:
Hi, I suggest all will become clear when you Google "InvokeRequired"
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
First, pass the Computer Name to RunWorkerAsync():
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not bw.IsBusy = True Then
            bw.RunWorkerAsync(TextBox1.Text)
        End If
    End Sub

Open in new window


Then you can grab it in DoWork() with "e.Argument".  Set "e.Result" to your output:
    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Try
            Dim str_ServerName As String = e.Argument.ToString
            Dim pc As New PerformanceCounter("System", "System Up Time", "", str_ServerName)
            pc.NextValue()
            Dim ts As TimeSpan = TimeSpan.FromSeconds(pc.NextValue)
            e.Result = str_ServerName & " has been up for " & ts.Days & " days, " & ts.Hours & " hours, " & ts.Minutes & " minutes, " & " and " & ts.Seconds & " seconds."
        Catch ex As Exception
            e.Result = "Workstation Uptime not found"
        End Try
    End Sub

Open in new window


Finally, grab "e.Result" in the RunWorkerCompleted() event:
    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Dim result As String = e.Result
        MessageBox.Show(result)
    End Sub

Open in new window

0
 
käµfm³d 👽Commented:
I agree with Mike:  The BW supports passing data back to the UI via its established events. There is no need for CheckForIllegalCrossThreadCalls, BeginInvoke, or InvokeRequired as the others have mentioned.
0
 
AndyAinscowCommented:
From the help files about the BackgroundWorker:
http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

To pass data back to the calling process, set the Result property of the DoWorkEventArgs object that is passed to the event handler. This value can be read when the RunWorkerCompleted event is raised at the end of the operation.
0
 
derek7467Author Commented:
thank you
0
 
AndyAinscowCommented:
ps.
Reading the help files could result in a quicker answer than just asking a question and waiting.
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now