VB.Net how to run a function in a seperate thread

Hi Experts
I have two simple functions - one checks the status of a server and returns true or false, the other sends an email based
on data passed to it.    I need to free up the GUI while these functions operate and would like to operate them on separate threads so that the continuous progressbar runs and the users can continue.
Please could someone give me an example of how to run a function like that on a separate thread, how to pass data to it and receive a result from it.  I've seen many examples on the web of the backgroundworker, but none that operate it as a function. Many thanks
LVL 2
PNRTAsked:
Who is Participating?
 
Fernando SotoRetiredCommented:
Hi PNRT;

Add a BackgroundWorker component to your form and code like below will show how it can be done.

Imports System.ComponentModel

Public Class Form1

    Public Sub New()
        InitializeComponent()
        backgroundWorker1.WorkerReportsProgress = True
        backgroundWorker1.WorkerSupportsCancellation = True
    End Sub

    Private Function GetServerStatus(ByVal server As String) As Boolean
        Return True '' Change this function to return the server status 
    End Function

    '' Use as many parameters as needed
    Private Sub SendEmail(ByVal emailAddress As String)
        Debug.Print("Email Sent to : " & emailAddress)
    End Sub

    Private Sub startAsyncButton_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles startAsyncButton.Click
        If BackgroundWorker1.IsBusy <> True Then
            ' Start the asynchronous operation passing in a server to check
            BackgroundWorker1.RunWorkerAsync({"Server1", "Tom@EE.com"})
        End If
    End Sub

    Private Sub cancelAsyncButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cancelAsyncButton.Click
        If backgroundWorker1.WorkerSupportsCancellation = True Then
            ' Cancel the asynchronous operation.
            backgroundWorker1.CancelAsync()
        End If
    End Sub

    ' This event handler is where the time-consuming work is done. 
    Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        worker.ReportProgress(0)
        Dim serverToCheck As String = e.Argument(0).ToString()
        Dim email As String = e.Argument(1).ToString()
        Dim serverStatus As Boolean = GetServerStatus(serverToCheck)
        worker.ReportProgress(50)
        SendEmail(email)
        worker.ReportProgress(100)
    End Sub

    ' This event handler updates the progress. 
    Private Sub backgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        resultLabel.Text = resultLabel.Text & vbCrLf & (e.ProgressPercentage.ToString() + "% completed")
    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 BackgroundWorker1.RunWorkerCompleted
        resultLabel.Text = resultLabel.Text & vbCrLf
        If e.Cancelled = True Then
            resultLabel.Text = resultLabel.Text & "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            resultLabel.Text = resultLabel.Text & "Error: " & e.Error.Message
        Else
            resultLabel.Text = resultLabel.Text & "Done!"
        End If
    End Sub

End Class

Open in new window

0
 
CodeCruiserCommented:
Example code for starting thread here

https://support.microsoft.com/en-us/kb/315577


Private Sub Form1_Load( _
    ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyBase.Load

    Private trd As Thread
    trd = New Thread(AddressOf ThreadTask)
    trd.IsBackground = True
    trd.Start()
End Sub


Private Sub ThreadTask()
    Dim stp As Integer
    Dim newval As Integer
    Dim rnd As New Random()

    Do
        stp = ProgressBar1.Step * rnd.Next(-1, 2)
        newval = ProgressBar1.Value + stp
        If newval > ProgressBar1.Maximum Then
            newval = ProgressBar1.Maximum
        ElseIf newval < ProgressBar1.Minimum Then
            newval = ProgressBar1.Minimum
        End If

        ProgressBar1.Value = newval

        Thread.Sleep(100)
    Loop
End Sub

Open in new window



Also

https://msdn.microsoft.com/en-us/library/ts553s52(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
0
 
PNRTAuthor Commented:
Thanks, I've seen this many times, but as per my question, I was looking for how to operate a function, sending data to it and receiving a result from it
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

 
R555BCommented:
So do you want to check the server status then send an email based on it?

How does the data get passed to the second function ?
0
 
CodeCruiserCommented:
Have you seen section "Retrieving data with callback methods" in 2nd link?
0
 
PNRTAuthor Commented:
Hi R555B, thanks for the reply, they are just two simple functions the first gets sent the IP of the server to ping and returns true or false.  The second function gets sent, server, port, user/password and email address and sends and email.
Returning true or false if successful.  Both work fine but I was just trying to get the same functionality without freezing the GUI

Hi CodeCruiser.  thanks for the reply.   LOL, if I wasn't confused before, then reading about callback methods really did it.  Sorry.
0
 
R555BCommented:
OK, if I was doing that, I'd do something like this....


dim b as new backgroundworker
addhandler b.dowork, addressof Testsub
dim parameters as string = IP & "//" & server & "//" & port
b.runworkerasync(parameters)


public sub testsub(byval sender as object, byval e as doworkeventargs)
dim sub_params() as string = e.argument.tostring.split("//")
dim IP as string = spilts(0)

ping_function(ip)
mail_function(other parameters...)

end sub

Open in new window



Or something along those lines. Pass all the parameters to a background worker as one big string. Parse them into separate variables and the pass those to the functions.
If youve got multiple servers, ports etc youll want to loop it somehow as well.
0
 
R555BCommented:
or alternativley...

dim b as new backgroundworker
addhandler b.dowork, addressof ping_function
b.runworkerasync(Ip_address)

Open in new window


That may not work as well though as I think the backgroundworker stil expects things to be passed to it as e.Arguments as opposed to a regular parameter.
You may find that way the ping_function returns an exception as its got nothing to ping
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.