|
-
Jan 12th, 2010, 09:38 AM
#1
Thread Starter
Fanatic Member
Threading problem
Hi Guys,
I am using VB.NET (2008). I have tried using threading before and I did encounter issues. Then I wrote in this forum and jmcilhinney helped me. It did solve my problem and I am grateful for that. The thread can be found here
Thread here
My current problem is as follows :-
- I have a form with various controls incl a timer control.
- Task: when i click on start , timer starts and at regular intervals it downloads a file and processes it.
- Then it becomes idle for a while before repeating it.
- No threading used in this form so far.
Now when the timer is idle then I need to do some processing. So I thought that I can create a thread and use that thread to do the processing so that the application remains responsive.
I wrote the following code :
Code:
' General
Dim DataThread as Thread
Private Sub TimerMain_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TimerMain.Tick
If timerjobdone = True then
Call ExecuteThreadCode()
TimerMain.Interval = 10000
end if
End Sub
Private Sub ExecuteThreadCode()
DataThread = new thread(addressof DoProcessing)
Datathread.start
End Sub
Private sub DoProcessing()
' Here I need to access the label of the form so i need to do invoke method
' I do some file reading and other processing here
End sub
Now when the code segment executes my application becomes unresponsive. I mean i used threading to make program more accessible to user or responsive but it does not work.
Will be glad if anyone can help me out.
Thanks a lot,
GR
-
Jan 12th, 2010, 09:42 AM
#2
Re: Threading problem
You don't actually need the ExecuteThreadCode method, as you could move what is inside of it into the timer. It doesn't hurt, though, if you find it cleaner this way.
I would say that the issue lies in the part that you didn't post: The thread method itself.
My usual boring signature: Nothing
 
-
Jan 12th, 2010, 11:53 AM
#3
Thread Starter
Fanatic Member
Re: Threading problem
The code inside the thread method is bit long and complex. It's basically opening files, processing them and downloading some small files and processing them.
What I wanted to know is why it is not working like an independant thread? why does my program become unresponsive.
-
Jan 12th, 2010, 02:31 PM
#4
Re: Threading problem
You also mentioned interacting with form controls from the background thread. Perhaps that was done in a way that blocks the UI. The code you have shown doesn't have any obvious issues in it. However, you can put a breakpoint on the first line in the timer event, and step through it. If it is blocking somewhere, you will see it. If it isn't, and the timer event code finishes up normally, then it is the background thread itself that is blocking the UI thread. Without seeing the code, nobody can answer that definitively. However, if there is lots of code...perhaps nobody can answer definitively anyhow.
The first thing I would do would be to step through the timer event. That shouldn't cause a problem as you have it now, so the next thing I would do would be to take a look at any interactions between the thread and the UI.
My usual boring signature: Nothing
 
-
Jan 12th, 2010, 04:33 PM
#5
Re: Threading problem
Wouldn't this be a good time to put some Debug.Writeline statements into the main code, the timer events and the thread methods?
Won't all these Debug.Writeline's appear in the OUTPUT window telling you exactly where the flow of the code is going?
-
Jan 12th, 2010, 11:15 PM
#6
Thread Starter
Fanatic Member
Re: Threading problem
The code for the sub that does the processing (which I didnt write before) is :
Code:
Private Sub DoProcessing()
If Me.InvokeRequired = True Then
Me.lblstatus.Invoke(New MethodInvoker(AddressOf DoProcessing))
Else
Try
' this function will check for data.
' CHECKS/Validation
If Now.DayOfWeek = DayOfWeek.Saturday Then Exit Sub
Dim FPath As String = DataPath & "\Abc.txt"
If File.Exists(FPath) = False Then Exit Sub
Dim CTime As DateTime = Now, GoAhead As Boolean = False, Cnt As Integer = 0
If Format$(CTime, "HHmm").ToString.Substring(3, 1) = "5" Or Format$(CTime, "HHmm").ToString.Substring(3, 1) = "0" Then
GoAhead = True ' means we have 5 min in hand and we can go ahead and check
Else
Do
Cnt = Cnt + 1
CTime = CTime.AddMinutes(1)
If Format$(CTime, "HHmm").ToString.Substring(3, 1) = "5" Or Format$(CTime, "HHmm").ToString.Substring(3, 1) = "0" Then Exit Do
If Cnt > 5 Then Exit Do ' EMERGENCY EXIT
Loop
If Cnt >= 3 Then GoAhead = True Else GoAhead = False
End If
If GoAhead = False Then Exit Sub
' Checks Done
Dim FileData() As String = File.ReadAllLines(FPath), FTemp() As String
Dim FileTime As DateTime, FileDate As Date, Ticks() As String, EndTime As DateTime
Dim RecCount As Long = 0, ReadCounter As Long = 0
ReDim Ticks(0)
If UBound(FileData) < 3 Then
Exit Sub ' get out
End If
lblstatus.Text = "Status: Checking for data..." : lblstatus.Refresh()
For i As Long = UBound(FileData) To LBound(FileData) Step -1
If FileData(i).Trim = "" Then Continue For
ReadCounter += 1
FileDate = New Date(FileData(i).ToString.Substring(6, 4), FileData(i).ToString.Substring(3, 2), FileData(i).ToString.Substring(0, 2))
RecCount = i
If ReadCounter = 1 Then ' Get End Time
FTemp = FileData(i).Split(",")
EndTime = New DateTime(Now.Date.Year, Now.Date.Month, Now.Date.Day, FTemp(1).Substring(0, 2), FTemp(1).Substring(2, 2), 0)
End If
If Format$(FileDate, "yyyyMMdd") <> Format$(Now.Date, "yyyyMMdd") Then
Exit For
End If
Next
If RecCount = UBound(FileData) Then
' no rec found display message and get out
lblstatus.Text = "Status: Data check completed" lblstatus.Refresh()
Exit Sub
End If
ReadCounter = 0 : RecCount += 1
FileTime = New DateTime(Now.Date.Year, Now.Date.Month, Now.Date.Day, "09", "05", "0")
Do
ReadCounter = ReadCounter + 1
If RecExistsInArray(FileData, RecCount, Format$(FileTime, "HHmm")) = True Then
FileTime = FileTime.AddMinutes(5)
Else
ReDim Preserve Ticks(UBound(Ticks) + 1)
Ticks(UBound(Ticks)) = Format$(FileTime, "HHmm")
FileTime = FileTime.AddMinutes(5)
End If
If FileTime = EndTime Then Exit Do
If ReadCounter > 70 Then Exit Do ' Emergency Exit
Loop
' NOW DOWNLOAD THOSE Files
Dim DownloadedTicks() As String : ReDim DownloadedTicks(0)
For i As Integer = 1 To UBound(Ticks)
Try
If File.Exists(Application.StartupPath & "\" & Ticks(i) & ".dat") = True Then File.Delete(Application.StartupPath & "\" & Ticks(i) & ".dat")
My.Computer.Network.DownloadFile("www.mysite.com/" & Format(DateTimePicker1.Value.Date, "ddMMyy") & "/" & Ticks(i) & ".dat", Application.StartupPath & "\" & Ticks(i) & ".dat")
ReDim Preserve DownloadedTicks(UBound(DownloadedTicks) + 1) ' tick downloaded
DownloadedTicks(UBound(DownloadedTicks)) = Ticks(i)
Catch ex As Exception
' means couldnt download or find file
End Try
Next
If UBound(DownloadedTicks) = 0 Then
' didnt find file so quit/exit
lblstatus.Text = "Status: Data check completed" : lblstatus.Refresh()
Exit Sub
End If
' Found some/all missed ticks
' Read them
' File Reading routine not pasted right now
lblstatus.Text = "Status: Data updated successfully "
Catch ex As Exception
Threading.Thread.Sleep(1500)
End Try
End If ' Endif for Me.Invoke Required
End Sub
Now inspite of executing the above code in thread, the application locks up till processing does not finish. Why? Do i need to use doevents or I dunno why? I did use debug to check the flow and found no problems in the flow.
Please help me here.
Thank you.
-
Jan 12th, 2010, 11:54 PM
#7
Re: Threading problem
The problem is that you're NOT executing that code in a separate thread. You start a new thread and call DoProcessing, then the very first thing that DoProcessing does is invoke a call back to the UI thread and ALL the work is done there.
You are supposed to do all your work on the worker thread and then invoke a call back to the UI thread ONLY to access the UI. Get rid of any that If block and any interaction with the UI from that method. Then that whole method will be executed on the worker thread. You then write a new method ONLY for interaction with the UI, e.g.
vb.net Code:
Private Sub UpdateLabel(ByVal text As String) If Me.lblstatus.InvokeRequired Then Me.lblstatus.Invoke(New MethodInvoker(AddressOf DoProcessing), text) Else Me.lblstatus.Text = text End If End Sub
You can then call that method from DoProcessing to update lblstatus.
-
Jan 13th, 2010, 12:45 AM
#8
Thread Starter
Fanatic Member
Re: Threading problem
 Originally Posted by jmcilhinney
The problem is that you're NOT executing that code in a separate thread. You start a new thread and call DoProcessing, then the very first thing that DoProcessing does is invoke a call back to the UI thread and ALL the work is done there.
You are supposed to do all your work on the worker thread and then invoke a call back to the UI thread ONLY to access the UI. Get rid of any that If block and any interaction with the UI from that method. Then that whole method will be executed on the worker thread. You then write a new method ONLY for interaction with the UI, e.g.
vb.net Code:
Private Sub UpdateLabel(ByVal text As String)
If Me.lblstatus.InvokeRequired Then
Me.lblstatus.Invoke(New MethodInvoker(AddressOf DoProcessing), text)
Else
Me.lblstatus.Text = text
End If
End Sub
You can then call that method from DoProcessing to update lblstatus.
Thanks buddy for your help. I removed the invoke call to UI thread statements. The DoProcessing sub now does not directly access the UI.
But still the application behaves like before that is it locks up till the processing isn't over. I am unable to understand why?. 
Code:
Private Sub DoProcessing()
Try
' this function will check for data.
' CHECKS/Validation
If ProgramSettings.CheckForMissedData = False Then Exit Sub
If Now.DayOfWeek = DayOfWeek.Saturday Then Exit Sub
Dim FPath As String = DataPath & "\Abc.txt"
If File.Exists(FPath) = False Then Exit Sub
Dim CTime As DateTime = Now, GoAhead As Boolean = False, Cnt As Integer = 0
If Format$(CTime, "HHmm").ToString.Substring(3, 1) = "5" Or Format$(CTime, "HHmm").ToString.Substring(3, 1) = "0" Then
GoAhead = True ' means we have 5 min in hand and we can go ahead and check
Else
Do
Cnt = Cnt + 1
CTime = CTime.AddMinutes(1)
If Format$(CTime, "HHmm").ToString.Substring(3, 1) = "5" Or Format$(CTime, "HHmm").ToString.Substring(3, 1) = "0" Then Exit Do
If Cnt > 5 Then Exit Do ' EMERGENCY EXIT
Loop
If Cnt >= 3 Then GoAhead = True Else GoAhead = False
End If
If GoAhead = False Then Exit Sub
' Checks Done
Dim FileData() As String = File.ReadAllLines(FPath), FTemp() As String
Dim FileTime As DateTime, FileDate As Date, Ticks() As String, EndTime As DateTime
Dim RecCount As Long = 0, ReadCounter As Long = 0
ReDim Ticks(0)
If UBound(FileData) < 3 Then
Exit Sub ' get out
End If
Call LabelReset("Status: Checking for missed data")
For i As Long = UBound(FileData) To LBound(FileData) Step -1
If FileData(i).Trim = "" Then Continue For
ReadCounter += 1
FileDate = New Date(FileData(i).ToString.Substring(6, 4), FileData(i).ToString.Substring(3, 2), FileData(i).ToString.Substring(0, 2))
RecCount = i
If ReadCounter = 1 Then ' Get End Time
FTemp = FileData(i).Split(",")
EndTime = New DateTime(Now.Date.Year, Now.Date.Month, Now.Date.Day, FTemp(1).Substring(0, 2), FTemp(1).Substring(2, 2), 0)
End If
If Format$(FileDate, "yyyyMMdd") <> Format$(Now.Date, "yyyyMMdd") Then
Exit For
End If
Next
If RecCount = UBound(FileData) Then
Exit Sub
End If
ReadCounter = 0 : RecCount += 1
FileTime = New DateTime(Now.Date.Year, Now.Date.Month, Now.Date.Day, "09", "05", "0")
Do
ReadCounter = ReadCounter + 1
If RecExistsInArray(FileData, RecCount, Format$(FileTime, "HHmm")) = True Then
FileTime = FileTime.AddMinutes(5)
Else
ReDim Preserve Ticks(UBound(Ticks) + 1)
Ticks(UBound(Ticks)) = Format$(FileTime, "HHmm")
FileTime = FileTime.AddMinutes(5)
End If
If FileTime = EndTime Then Exit Do
If ReadCounter > 70 Then Exit Do ' Emergency Exit
Loop
' Done now check if there were missed ticks or not
If UBound(Ticks) = 0 Then
' All ticks present so far
Call LabelReset("Status: No ticks missed so far")
Exit Sub
End If
' NOW DOWNLOAD THOSE TICKS
Dim DownloadedTicks() As String : ReDim DownloadedTicks(0)
For i As Integer = 1 To UBound(Ticks)
Try
If File.Exists(Application.StartupPath & "\" & Ticks(i) & ".dat") = True Then File.Delete(Application.StartupPath & "\" & Ticks(i) & ".dat")
My.Computer.Network.DownloadFile("http://www.mysite.com/" & Format(DateTimePicker1.Value.Date, "ddMMyy") & "/" & Ticks(i) & ".dat", Application.StartupPath & "\" & Ticks(i) & ".dat")
ReDim Preserve DownloadedTicks(UBound(DownloadedTicks) + 1) ' tick downloaded
DownloadedTicks(UBound(DownloadedTicks)) = Ticks(i)
Catch ex As Exception
' means couldnt download or find file
End Try
Next
If UBound(DownloadedTicks) = 0 Then
' didnt find file so quit/exit
' lblstatus.Text = "Status: Missed data check completed" : lblstatus.Refresh()
' commented above
Exit Sub
End If
' Found some/all ticks
' Read data files in array
' Code for Processing File Not Pasted
Call LabelReset("Status: DONE")
Catch ex As Exception
End Try
End Sub
Private Sub LabelReset(ByVal text As String)
If Me.InvokeRequired = True Then
Me.lblstatus.Invoke(New MethodInvoker(AddressOf DoProcessing), text)
Else
lblstatus.Text = text : lblstatus.Refresh()
End If
End Sub
' Timer code
Private Sub TimerMain_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TimerMain.Tick
If LastCheckOK() = True Then
lblstatus.Text = "Status: Waiting for next data" : lblstatus.Refresh()
TimerMain.Interval = GetTimerInterval()
' calling thread
MissedTickThread = New Thread(AddressOf DoProcessing)
MissedTickThread.Start()
Exit Sub
End If
End Sub
Cheers.
Last edited by greatchap; Jan 13th, 2010 at 07:12 AM.
-
Jan 13th, 2010, 07:24 AM
#9
Thread Starter
Fanatic Member
Re: Threading problem
I tried using background worker control but it didnt work the way I wanted. My app still locks up until processing is completed. Kinda strange isn't it ?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|