mcguirestick
asked on
VB 2005 BackgroundWorker Problem passing values to commnad buttons
I know there are a few threads regarding this matter but i still can not get my head round this.
I have a windows form with a number of Command Buttons on. Every so ofter a timer fires which opens a spreadsheet and updates the Caption and backColour of these buttons. When the timer fires it starts the thread (BackgroundWorker) and all runs fine till i try to change the caption on the button the program then crashes. As i am updating 18 button concesotivly i realise you need to pass the result back but can not figure how. I have seen one solution that switches threads but sort of defeats the point of running in a seperate thread in the first place.
Here is a bit of the code
Public Sub FleetCheck()
Dim Line As Integer
Dim SheetNo As Integer
Dim TempStr As String
Dim TempStr2 As String
Dim Found As Boolean
Dim I, A, B As Integer
Dim SheetTemp As Integer
Dim Dates, Times As String
Dates = Mid(Now, 1, 10)
Times = Mid(Now, 12, 5)
xlsApp.ActiveWorkbook.Refr eshAll()
' check no of rows on spread sheet
Line = 4
Do While Found = False
TempStr = xlsSheet.Range("A" & Line).Value
Line = Line + 1
If TempStr = "" Then Found = True
Loop
SheetNo = Line
'MsgBox("Found it " & SheetNo)
Found = False
Line = 0
Do While Found = False
If CallSignArray(Line) = "" Then Found = True
Line = Line + 1
Loop
ArrayNo = Line - 2
'MsgBox(ArrayNo)
ReDim FleetArray(ArrayNo, 7)
B = 0
SheetTemp = SheetNo + 4
For A = 0 To ArrayNo
For I = 4 To SheetTemp
TempStr = CallSignArray(A)
TempStr2 = xlsSheet.Range("D" & I).Value
If TempStr = TempStr2 Then
FleetArray(B, 0) = xlsSheet.Range("D" & I).Value 'Callsign
FleetArray(B, 1) = xlsSheet.Range("A" & I).Value ' Fleet
FleetArray(B, 2) = xlsSheet.Range("E" & I).Value 'CAD
FleetArray(B, 3) = xlsSheet.Range("F" & I).Value 'Status
FleetArray(B, 4) = xlsSheet.Range("H" & I).Value 'Mins
FleetArray(B, 5) = xlsSheet.Range("I" & I).Value & xlsSheet.Range("J" & I).Value 'Map
FleetArray(B, 6) = xlsSheet.Range("L" & I).Value 'Speed
FleetArray(B, 7) = xlsSheet.Range("N" & I).Value 'Location
B = B + 1
End If
Next
Next
'Fill Call Signs labels
A = 0
If FleetArray(A, 1) <> "" Then
FrmMain.Cmd1.Text = FleetArray(A, 0) & " " & FleetArray(A, 4)
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd1.BackColor = Color.GreenYellow
A = A + 1
End If
If FleetArray(A, 1) <> "" Then
FrmMain.Cmd2.Text = FleetArray(A, 0) & " " & FleetArray(A, 4) ' ******** Program crashes here ****
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd2.BackColor = Color.GreenYellow
A = A + 1
End If
If FleetArray(A, 1) <> "" Then
FrmMain.Cmd3.Text = FleetArray(A, 0) & " " & FleetArray(A, 4)
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd3.BackColor = Color.GreenYellow
A = A + 1
End If
etc etc etc
Any help would be appreciated
I have a windows form with a number of Command Buttons on. Every so ofter a timer fires which opens a spreadsheet and updates the Caption and backColour of these buttons. When the timer fires it starts the thread (BackgroundWorker) and all runs fine till i try to change the caption on the button the program then crashes. As i am updating 18 button concesotivly i realise you need to pass the result back but can not figure how. I have seen one solution that switches threads but sort of defeats the point of running in a seperate thread in the first place.
Here is a bit of the code
Public Sub FleetCheck()
Dim Line As Integer
Dim SheetNo As Integer
Dim TempStr As String
Dim TempStr2 As String
Dim Found As Boolean
Dim I, A, B As Integer
Dim SheetTemp As Integer
Dim Dates, Times As String
Dates = Mid(Now, 1, 10)
Times = Mid(Now, 12, 5)
xlsApp.ActiveWorkbook.Refr
' check no of rows on spread sheet
Line = 4
Do While Found = False
TempStr = xlsSheet.Range("A" & Line).Value
Line = Line + 1
If TempStr = "" Then Found = True
Loop
SheetNo = Line
'MsgBox("Found it " & SheetNo)
Found = False
Line = 0
Do While Found = False
If CallSignArray(Line) = "" Then Found = True
Line = Line + 1
Loop
ArrayNo = Line - 2
'MsgBox(ArrayNo)
ReDim FleetArray(ArrayNo, 7)
B = 0
SheetTemp = SheetNo + 4
For A = 0 To ArrayNo
For I = 4 To SheetTemp
TempStr = CallSignArray(A)
TempStr2 = xlsSheet.Range("D" & I).Value
If TempStr = TempStr2 Then
FleetArray(B, 0) = xlsSheet.Range("D" & I).Value 'Callsign
FleetArray(B, 1) = xlsSheet.Range("A" & I).Value ' Fleet
FleetArray(B, 2) = xlsSheet.Range("E" & I).Value 'CAD
FleetArray(B, 3) = xlsSheet.Range("F" & I).Value 'Status
FleetArray(B, 4) = xlsSheet.Range("H" & I).Value 'Mins
FleetArray(B, 5) = xlsSheet.Range("I" & I).Value & xlsSheet.Range("J" & I).Value 'Map
FleetArray(B, 6) = xlsSheet.Range("L" & I).Value 'Speed
FleetArray(B, 7) = xlsSheet.Range("N" & I).Value 'Location
B = B + 1
End If
Next
Next
'Fill Call Signs labels
A = 0
If FleetArray(A, 1) <> "" Then
FrmMain.Cmd1.Text = FleetArray(A, 0) & " " & FleetArray(A, 4)
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd1.BackColor = Color.GreenYellow
A = A + 1
End If
If FleetArray(A, 1) <> "" Then
FrmMain.Cmd2.Text = FleetArray(A, 0) & " " & FleetArray(A, 4) ' ******** Program crashes here ****
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd2.BackColor = Color.GreenYellow
A = A + 1
End If
If FleetArray(A, 1) <> "" Then
FrmMain.Cmd3.Text = FleetArray(A, 0) & " " & FleetArray(A, 4)
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd3.BackColor = Color.GreenYellow
A = A + 1
End If
etc etc etc
Any help would be appreciated
Hi mcguirestick;
I am assuming that the code above is in the BackgroundWorker thread. It is not allowed to modify the controls of a GUI from another thread, which is known as a cross thread error.
In the BackgroundWorker model there are two methods that you can place code to modify the controls of a GUI. One is the ProgressChanged method and the other is RunWorkerCompleted method and this is because the system make a call to the GUI thread to make the change.
If you do not want to use one of the above methods then you will have to do something like this.
' At class level define delegate to be called from another thread. In this example I am updating a
' Ritch text box.
Private Delegate Sub rtbUpdateDelegate(ByVal msg As String)
' From within the thread code to update a GUI define a variable with the delegate
Dim rtbSafeUpdate As New rtbUpdateDelegate(AddressO f UpdateTargetRtb)
'....
' tcOutput is a TabControl on a GUI which has the RichTextbox and rtbSafeUpdate is the delegate that
' will do the update for the thread. Also arg is a string to be sent to the RichTextBox.
tcOutput.Invoke(rtbSafeUpd ate, arg)
' The delegated method to do the acutual update
Private Sub UpdateTargetRtb(ByVal msg As String)
' This function is called from another thread to update the
' RichTextBox for Replace with matches
rtbReplaceResults.Text = msg
End Sub
Fernando
I am assuming that the code above is in the BackgroundWorker thread. It is not allowed to modify the controls of a GUI from another thread, which is known as a cross thread error.
In the BackgroundWorker model there are two methods that you can place code to modify the controls of a GUI. One is the ProgressChanged method and the other is RunWorkerCompleted method and this is because the system make a call to the GUI thread to make the change.
If you do not want to use one of the above methods then you will have to do something like this.
' At class level define delegate to be called from another thread. In this example I am updating a
' Ritch text box.
Private Delegate Sub rtbUpdateDelegate(ByVal msg As String)
' From within the thread code to update a GUI define a variable with the delegate
Dim rtbSafeUpdate As New rtbUpdateDelegate(AddressO
'....
' tcOutput is a TabControl on a GUI which has the RichTextbox and rtbSafeUpdate is the delegate that
' will do the update for the thread. Also arg is a string to be sent to the RichTextBox.
tcOutput.Invoke(rtbSafeUpd
' The delegated method to do the acutual update
Private Sub UpdateTargetRtb(ByVal msg As String)
' This function is called from another thread to update the
' RichTextBox for Replace with matches
rtbReplaceResults.Text = msg
End Sub
Fernando
ASKER
I will give these two ago tomorrow. FernandoSoto: mentions using process changed method is that more complicated to use as i am a novice to VB 2005 but i think i do understand the first example. I will let you all know tomorrow
Thanks Terry
Thanks Terry
Hi mcguirestick;
Using the process changed method is much easier then the other way. Below is sample code of a BackgroundWorker thread that makes a call to the BackgroundWorker.ReportPro gress which raises the event ProgressChanged where you can direct interact with the GUI without cross thread violations. This sample code does a file search recursively and interfaces directly with the GUI. Note that the ProgressChanged event does not have to just report changes but can be used to changes the values of the forms controls.
This code sample assumes that the form has the following controls on it:
TextBox called txtSearchPath
TextBox called txtSearchPattern
Label called lblMessage
Button called btnStart
ListBox called lstFiles
Imports System.IO
Public Class SearchFilesFrm
' To set up for a background operation, add an event handler for the DoWork event.
' Call your time-consuming operation in this event handler. To start the operation,
' call RunWorkerAsync. To receive notifications of progress updates, handle the
' ProgressChanged event. To receive a notification when the operation is completed,
' handle the RunWorkerCompleted event.
' Note
' You must be careful not to manipulate any user-interface objects in your DoWork
' event handler. Instead, communicate to the user interface through the
' ProgressChanged and RunWorkerCompleted events.
' If your background operation requires a parameter, call RunWorkerAsync with your
' parameter. Inside the DoWork event handler, you can extract the parameter from
' the DoWorkEventArgs.Argument property.
' Store the results of the search
Private Files As List(Of String)
' Used to prevent nested calls to ProgressChanged
Private CallInProgress As Boolean
' The Worker thread
Private WithEvents BgWorker As New System.ComponentModel.Back groundWork er
Private Sub SearchFilesFrm_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
' Enable ProgressChanged and Cancellation mothed
BgWorker.WorkerReportsProg ress = True
BgWorker.WorkerSupportsCan cellation = True
End Sub
' Start and Stop the search
Private Sub btnStart_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnStart.Click
If btnStart.Text = "Start" Then
If Not Directory.Exists(txtSearch Path.Text. Trim()) Then
MessageBox.Show("The Search Directory does not exist", _
"Path Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
If txtSearchPattern.Text.Trim () = "" Then txtSearchPattern.Text = "*"
Dim arguments() As String = {txtSearchPath.Text.Trim() , _
txtSearchPattern.Text.Trim ()}
lstFiles.Items.Clear()
' Start the background worker thread. Thread runs in DoWork event.
BgWorker.RunWorkerAsync(ar guments)
btnStart.Text = "Stop"
Else
BgWorker.CancelAsync()
End If
End Sub
' Start the Asynchronous file search. The background thread does it work from
' this event.
Private Sub BgWorker_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWo rkEventArg s) Handles BgWorker.DoWork
'Retrieve the search path which was requested
Dim path As String = DirectCast(e.Argument, String())(0)
Dim pattern As String = DirectCast(e.Argument, String())(1)
' Invoke the worker procedure
Files = New List(Of String)
SearchFiles(path, pattern)
' Return a result to the RunWorkerCompleted event
Dim message As String = String.Format("Found {0} Files", Files.Count)
e.Result = message
End Sub
' Recursively search directory and sub directories
Private Sub SearchFiles(ByVal path As String, ByVal pattern As String)
' Displat message
Dim message As String = String.Format("Parsing Directory {0}", path)
BgWorker.ReportProgress(0, message)
'Read the files and if the Stop button is pressed cancel the operation
For Each fileName As String In Directory.GetFiles(path, pattern)
If BgWorker.CancellationPendi ng Then Return
Files.Add(fileName)
Next
For Each dirName As String In Directory.GetDirectories(p ath)
If BgWorker.CancellationPendi ng Then Return
SearchFiles(dirName, pattern)
Next
End Sub
' The bacground thread calls this event when you make a call to ReportProgress
' It is OK to access user controls in the UI from this event.
' If you use a Progress Bar or some other control to report the tasks progress
' you should avoid unnecessary calls to ReportProgress method because this causes
' a thread switch which is a relatively expensive in terms of processing time.
Private Sub BgWorker_ProgressChanged(B yVal sender As Object, _
ByVal e As System.ComponentModel.Prog ressChange dEventArgs ) _
Handles BgWorker.ProgressChanged
' Reject a nested call.
If CallInProgress Then Return
CallInProgress = True
' Display the message received in the UserState property
lblMessage.Text = e.UserState.ToString()
' Display all files added since last call.
For idx As Integer = lstFiles.Items.Count To Files.Count - 1
lstFiles.Items.Add(Files(i dx))
Next
' If a Me.Refresh is in this code you will need to place a Application.DoEvents()
' otherwise the UI will not respond without them it works fine.
' Me.Refresh()
' Let the Windows OS process messages in the queue
' Application.DoEvents()
CallInProgress = False
End Sub
' The background thread calls this event just before it reaches the End Sub
' of the DoWork event. It is OK to access user controls in the UI from this event.
Private Sub BgWorker_RunWorkerComplete d(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunW orkerCompl etedEventA rgs) _
Handles BgWorker.RunWorkerComplete d
' Display the last message and reset the Start/Stop button text
lblMessage.Text = e.Result.ToString()
btnStart.Text = "Start"
End Sub
End Class
Fernando
Using the process changed method is much easier then the other way. Below is sample code of a BackgroundWorker thread that makes a call to the BackgroundWorker.ReportPro
This code sample assumes that the form has the following controls on it:
TextBox called txtSearchPath
TextBox called txtSearchPattern
Label called lblMessage
Button called btnStart
ListBox called lstFiles
Imports System.IO
Public Class SearchFilesFrm
' To set up for a background operation, add an event handler for the DoWork event.
' Call your time-consuming operation in this event handler. To start the operation,
' call RunWorkerAsync. To receive notifications of progress updates, handle the
' ProgressChanged event. To receive a notification when the operation is completed,
' handle the RunWorkerCompleted event.
' Note
' You must be careful not to manipulate any user-interface objects in your DoWork
' event handler. Instead, communicate to the user interface through the
' ProgressChanged and RunWorkerCompleted events.
' If your background operation requires a parameter, call RunWorkerAsync with your
' parameter. Inside the DoWork event handler, you can extract the parameter from
' the DoWorkEventArgs.Argument property.
' Store the results of the search
Private Files As List(Of String)
' Used to prevent nested calls to ProgressChanged
Private CallInProgress As Boolean
' The Worker thread
Private WithEvents BgWorker As New System.ComponentModel.Back
Private Sub SearchFilesFrm_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
' Enable ProgressChanged and Cancellation mothed
BgWorker.WorkerReportsProg
BgWorker.WorkerSupportsCan
End Sub
' Start and Stop the search
Private Sub btnStart_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnStart.Click
If btnStart.Text = "Start" Then
If Not Directory.Exists(txtSearch
MessageBox.Show("The Search Directory does not exist", _
"Path Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
If txtSearchPattern.Text.Trim
Dim arguments() As String = {txtSearchPath.Text.Trim()
txtSearchPattern.Text.Trim
lstFiles.Items.Clear()
' Start the background worker thread. Thread runs in DoWork event.
BgWorker.RunWorkerAsync(ar
btnStart.Text = "Stop"
Else
BgWorker.CancelAsync()
End If
End Sub
' Start the Asynchronous file search. The background thread does it work from
' this event.
Private Sub BgWorker_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWo
'Retrieve the search path which was requested
Dim path As String = DirectCast(e.Argument, String())(0)
Dim pattern As String = DirectCast(e.Argument, String())(1)
' Invoke the worker procedure
Files = New List(Of String)
SearchFiles(path, pattern)
' Return a result to the RunWorkerCompleted event
Dim message As String = String.Format("Found {0} Files", Files.Count)
e.Result = message
End Sub
' Recursively search directory and sub directories
Private Sub SearchFiles(ByVal path As String, ByVal pattern As String)
' Displat message
Dim message As String = String.Format("Parsing Directory {0}", path)
BgWorker.ReportProgress(0,
'Read the files and if the Stop button is pressed cancel the operation
For Each fileName As String In Directory.GetFiles(path, pattern)
If BgWorker.CancellationPendi
Files.Add(fileName)
Next
For Each dirName As String In Directory.GetDirectories(p
If BgWorker.CancellationPendi
SearchFiles(dirName, pattern)
Next
End Sub
' The bacground thread calls this event when you make a call to ReportProgress
' It is OK to access user controls in the UI from this event.
' If you use a Progress Bar or some other control to report the tasks progress
' you should avoid unnecessary calls to ReportProgress method because this causes
' a thread switch which is a relatively expensive in terms of processing time.
Private Sub BgWorker_ProgressChanged(B
ByVal e As System.ComponentModel.Prog
Handles BgWorker.ProgressChanged
' Reject a nested call.
If CallInProgress Then Return
CallInProgress = True
' Display the message received in the UserState property
lblMessage.Text = e.UserState.ToString()
' Display all files added since last call.
For idx As Integer = lstFiles.Items.Count To Files.Count - 1
lstFiles.Items.Add(Files(i
Next
' If a Me.Refresh is in this code you will need to place a Application.DoEvents()
' otherwise the UI will not respond without them it works fine.
' Me.Refresh()
' Let the Windows OS process messages in the queue
' Application.DoEvents()
CallInProgress = False
End Sub
' The background thread calls this event just before it reaches the End Sub
' of the DoWork event. It is OK to access user controls in the UI from this event.
Private Sub BgWorker_RunWorkerComplete
ByVal e As System.ComponentModel.RunW
Handles BgWorker.RunWorkerComplete
' Display the last message and reset the Start/Stop button text
lblMessage.Text = e.Result.ToString()
btnStart.Text = "Start"
End Sub
End Class
Fernando
ASKER
Hi,
I have tried both the diffrent suggestions and i am getting the same error on both.
The error is generated on this line
tcOutput.Invoke(rtbSafeUpd ate, arg)
The error is:-
An error occurred creating the form. See Exception.InnerException for details. The error is: ActiveX control '926a6756-7fc7-4427-bff2-c d69fa9f4f6 2' cannot be instantiated because the current thread is not in a single-threaded apartment.
Any
I have tried both the diffrent suggestions and i am getting the same error on both.
The error is generated on this line
tcOutput.Invoke(rtbSafeUpd
The error is:-
An error occurred creating the form. See Exception.InnerException for details. The error is: ActiveX control '926a6756-7fc7-4427-bff2-c
Any
Can you post you code as is now?
ASKER
I have command buttons on a form called Cmd1, Cmd2, Cmd3 etc on a frame called Frame3 on a form called FrmMain.
On pressing a command button this code gets fired:-
Private Sub Button13_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button13.Click
'Thread Code
BW1.RunWorkerAsync()
End Sub
This fires:-
Private Sub BW1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWo rkEventArg s) Handles BW1.DoWork
FleetCheck()
BW1.CancelAsync()
End Sub
Which Fires a Module Called FleetCheck:-
Public Sub FleetCheck()
Dim Line As Integer
Dim SheetNo As Integer
Dim TempStr As String
Dim TempStr2 As String
Dim Found As Boolean
Dim I, A, B As Integer
Dim SheetTemp As Integer
Dim Dates, Times As String
Dim rtbSafeUpdate As New rtbUpdateDelegate(AddressO f UpdateTargetRtb)
Dates = Mid(Now, 1, 10)
Times = Mid(Now, 12, 5)
xlsApp.ActiveWorkbook.Refr eshAll()
' check no of rows on spread sheet
Line = 4
Do While Found = False
TempStr = xlsSheet.Range("A" & Line).Value
Line = Line + 1
If TempStr = "" Then Found = True
Loop
SheetNo = Line
'MsgBox("Found it " & SheetNo)
Found = False
Line = 0
Do While Found = False
If CallSignArray(Line) = "" Then Found = True
Line = Line + 1
Loop
ArrayNo = Line - 2
'MsgBox(ArrayNo)
ReDim FleetArray(ArrayNo, 7)
B = 0
SheetTemp = SheetNo + 4
For A = 0 To ArrayNo
For I = 4 To SheetTemp
TempStr = CallSignArray(A)
TempStr2 = xlsSheet.Range("D" & I).Value
If TempStr = TempStr2 Then
FleetArray(B, 0) = xlsSheet.Range("D" & I).Value 'Callsign
FleetArray(B, 1) = xlsSheet.Range("A" & I).Value ' Fleet
FleetArray(B, 2) = xlsSheet.Range("E" & I).Value 'CAD
FleetArray(B, 3) = xlsSheet.Range("F" & I).Value 'Status
FleetArray(B, 4) = xlsSheet.Range("H" & I).Value 'Mins
FleetArray(B, 5) = xlsSheet.Range("I" & I).Value & xlsSheet.Range("J" & I).Value 'Map
FleetArray(B, 6) = xlsSheet.Range("L" & I).Value 'Speed
FleetArray(B, 7) = xlsSheet.Range("N" & I).Value 'Location
B = B + 1
End If
Next
Next
'Fill listview headers
FrmMain.ListView2.Clear()
FrmMain.ListView2.View = View.Details
FrmMain.ListView2.Columns. Add("CallS ign", 65, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("Fleet No", 65, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("CAD", 50, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("Statu s", 175, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("Mins" , 50, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("MapRe f", 105, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("Speed ", 65, HorizontalAlignment.Left)
FrmMain.ListView2.Columns. Add("Locat ion", 175, HorizontalAlignment.Left)
A = 0
If FleetArray(A, 1) <> "" Then
'MsgBox(FleetArray(A, 0))
'MsgBox(FleetArray(A, 4))
************** CRASHES HERE ************************** ********** ********** ********** ********** *
FrmMain.Frame3.Invoke(rtbS afeUpdate, "Hello")
FrmMain.Cmd1.Text = FleetArray(A, 0) & " " & FleetArray(A, 4)
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd1.BackColor = Color.GreenYellow
If FleetArray(A, 3) = "grn away from veh" Then FrmMain.Cmd1.BackColor = Color.Green
If FleetArray(A, 3) = "red at hosp" Then FrmMain.Cmd1.BackColor = Color.Red
If FleetArray(A, 3) = "red at scn" Then FrmMain.Cmd1.BackColor = Color.DeepPink
If FleetArray(A, 3) = "red to hosp" Then FrmMain.Cmd1.BackColor = Color.IndianRed
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd1.BackColor = Color.GreenYellow
If FleetArray(A, 3) = "unavailable" Then FrmMain.Cmd1.BackColor = Color.Pink
If FleetArray(A, 3) = "amb to scn" Then FrmMain.Cmd1.BackColor = Color.Orange
If FleetArray(A, 3) = "grn at sby" Then FrmMain.Cmd1.BackColor = Color.LimeGreen
If FleetArray(A, 3) = "green mob" Then FrmMain.Cmd1.BackColor = Color.LightGreen
If FleetArray(A, 3) = "uninterruptible rest break" Then FrmMain.Cmd1.BackColor = Color.DodgerBlue
A = A + 1
End If
For A = 0 To ArrayNo
'FrmMain.ListBox1.Items.Ad d(FleetArr ay(A, 0) & " - " & FleetArray(A, 1) & " - " & FleetArray(A, 2) & " - " & FleetArray(A, 3) & " - " & FleetArray(A, 4))
If FleetArray(A, 0) = "" Then Exit For
lSingleItem = FrmMain.ListView2.Items.Ad d(FleetArr ay(A, 0))
lSingleItem.SubItems.Add(F leetArray( A, 1))
Next
FrmMain.Frame3.Caption = "Vehicle Status on " & Dates & " at " & Times
End Sub
Finnally:-
Private Delegate Sub rtbUpdateDelegate(ByVal msg As String)
Private Sub UpdateTargetRtb(ByVal msg As String)
' This function is called from another thread to update the
' RichTextBox for Replace with matches
FrmMain.Cmd1.Text = msg
End Sub
On pressing a command button this code gets fired:-
Private Sub Button13_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button13.Click
'Thread Code
BW1.RunWorkerAsync()
End Sub
This fires:-
Private Sub BW1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWo
FleetCheck()
BW1.CancelAsync()
End Sub
Which Fires a Module Called FleetCheck:-
Public Sub FleetCheck()
Dim Line As Integer
Dim SheetNo As Integer
Dim TempStr As String
Dim TempStr2 As String
Dim Found As Boolean
Dim I, A, B As Integer
Dim SheetTemp As Integer
Dim Dates, Times As String
Dim rtbSafeUpdate As New rtbUpdateDelegate(AddressO
Dates = Mid(Now, 1, 10)
Times = Mid(Now, 12, 5)
xlsApp.ActiveWorkbook.Refr
' check no of rows on spread sheet
Line = 4
Do While Found = False
TempStr = xlsSheet.Range("A" & Line).Value
Line = Line + 1
If TempStr = "" Then Found = True
Loop
SheetNo = Line
'MsgBox("Found it " & SheetNo)
Found = False
Line = 0
Do While Found = False
If CallSignArray(Line) = "" Then Found = True
Line = Line + 1
Loop
ArrayNo = Line - 2
'MsgBox(ArrayNo)
ReDim FleetArray(ArrayNo, 7)
B = 0
SheetTemp = SheetNo + 4
For A = 0 To ArrayNo
For I = 4 To SheetTemp
TempStr = CallSignArray(A)
TempStr2 = xlsSheet.Range("D" & I).Value
If TempStr = TempStr2 Then
FleetArray(B, 0) = xlsSheet.Range("D" & I).Value 'Callsign
FleetArray(B, 1) = xlsSheet.Range("A" & I).Value ' Fleet
FleetArray(B, 2) = xlsSheet.Range("E" & I).Value 'CAD
FleetArray(B, 3) = xlsSheet.Range("F" & I).Value 'Status
FleetArray(B, 4) = xlsSheet.Range("H" & I).Value 'Mins
FleetArray(B, 5) = xlsSheet.Range("I" & I).Value & xlsSheet.Range("J" & I).Value 'Map
FleetArray(B, 6) = xlsSheet.Range("L" & I).Value 'Speed
FleetArray(B, 7) = xlsSheet.Range("N" & I).Value 'Location
B = B + 1
End If
Next
Next
'Fill listview headers
FrmMain.ListView2.Clear()
FrmMain.ListView2.View = View.Details
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
FrmMain.ListView2.Columns.
A = 0
If FleetArray(A, 1) <> "" Then
'MsgBox(FleetArray(A, 0))
'MsgBox(FleetArray(A, 4))
************** CRASHES HERE **************************
FrmMain.Frame3.Invoke(rtbS
FrmMain.Cmd1.Text = FleetArray(A, 0) & " " & FleetArray(A, 4)
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd1.BackColor = Color.GreenYellow
If FleetArray(A, 3) = "grn away from veh" Then FrmMain.Cmd1.BackColor = Color.Green
If FleetArray(A, 3) = "red at hosp" Then FrmMain.Cmd1.BackColor = Color.Red
If FleetArray(A, 3) = "red at scn" Then FrmMain.Cmd1.BackColor = Color.DeepPink
If FleetArray(A, 3) = "red to hosp" Then FrmMain.Cmd1.BackColor = Color.IndianRed
If FleetArray(A, 3) = "grn at stn" Then FrmMain.Cmd1.BackColor = Color.GreenYellow
If FleetArray(A, 3) = "unavailable" Then FrmMain.Cmd1.BackColor = Color.Pink
If FleetArray(A, 3) = "amb to scn" Then FrmMain.Cmd1.BackColor = Color.Orange
If FleetArray(A, 3) = "grn at sby" Then FrmMain.Cmd1.BackColor = Color.LimeGreen
If FleetArray(A, 3) = "green mob" Then FrmMain.Cmd1.BackColor = Color.LightGreen
If FleetArray(A, 3) = "uninterruptible rest break" Then FrmMain.Cmd1.BackColor = Color.DodgerBlue
A = A + 1
End If
For A = 0 To ArrayNo
'FrmMain.ListBox1.Items.Ad
If FleetArray(A, 0) = "" Then Exit For
lSingleItem = FrmMain.ListView2.Items.Ad
lSingleItem.SubItems.Add(F
Next
FrmMain.Frame3.Caption = "Vehicle Status on " & Dates & " at " & Times
End Sub
Finnally:-
Private Delegate Sub rtbUpdateDelegate(ByVal msg As String)
Private Sub UpdateTargetRtb(ByVal msg As String)
' This function is called from another thread to update the
' RichTextBox for Replace with matches
FrmMain.Cmd1.Text = msg
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi,
Thanks for all your work.
I did it a diffrent way in the end.
I basically populated the array with all the fields uring the new thread and then just read back the array and populated the command buttons using the Array. Its not perfect but so much faster than it was before.
Thanks
Terry
Thanks for all your work.
I did it a diffrent way in the end.
I basically populated the array with all the fields uring the new thread and then just read back the array and populated the command buttons using the Array. Its not perfect but so much faster than it was before.
Thanks
Terry
Not a problem, glad you got it working. ;=)
1.- So the first thing to do is create a Public Delegate sub
Public Delegate Sub printString_ToMainThread(B
2.- Let's say you have a textbox named txtReadingBufferNow
3.- Now on the BackgroundWorker thread you get the values you want (e.g. aCHR=somthing you want)
and you want to update the txtReadingBufferNow.text=a
You call
txtReadingBufferNow.BeginI
4.- ReadingNow_Display is a private or public sub that updates the main thread
Private Sub ReadingNow_Display(ByVal vTXT As String)
Me.txtReadingBufferNow.Tex
Me.txtReadingBufferNow.Ref
End Sub
I hope it helps