?
Solved

Can't understand Backgroundworker and intervals

Posted on 2008-11-12
16
Medium Priority
?
405 Views
Last Modified: 2012-06-22
We have 10 BackgroundWorkers in a project.
We have DoWork events on a couple and we also we want them to "sleep" for a specified period of time before
actually running again.

We do this at the end of the DoWork in one of the backgroundworkers named bwPatientRequests:
  System.Threading.Thread.Sleep(INTERVAL_PatientRequests) 'INTERVAL_PatientRequests = 180000
Doesn't this mean this thing should sleep for 3 min before it runs again.

Why is this one and another one running every minute?
We have one other one whose interval is set to one minute and in each of the ones we want to sleep we have a RunWorkerCompleted event and call Application.DoEvents() in each of them.

Any idea how we can make them have different intervals and sleep accordingly?

bwVisitRequests - should sleep 3 minutes (INTERVAL_VisitRequsts = 180000)
bwPatientRequests - should sleep 3 minutes (INTERVAL_PatientRequests = 180000)
bwProcessMessages - should sleep 1 minute. (INTERVAL_ProcessMessages = 10000)

bwProcessMessages processes the messages retrieved by the other two workers at their intevals.
0
Comment
Question by:Eddie Shipman
  • 11
  • 5
16 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 22945014
How are the background workers on your form?...Did you drop them there are design-time?...Are you creating them dynamically at run-time?
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22945352
Dropped on form. I didn't create this project, just debugging trying to figure out why it
is polling every minute .vs 3 minutes like we want.
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22945361
I may just replace the BW's with Timers and that way I KNOW when they will fire.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 22947416
Well...BackgroundWorkers don't restart themselves...they must be explicitly started with code.  How are they being launched?...can u show that code please?
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22949948
They are restarted in the RunWorkerCompleted events like this:

    Private Sub bwVisitRequests_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwVisitRequests.RunWorkerCompleted
        If iVisitRequestErrorCount > 10 Then
            LogErrorToFile("MORE THAN 10 ERRORS HAVE OCCURRED ON GETUPDATEDVISIT REQUEST.  STOPPED THIS CHANNEL AT " & Now.ToString, sFilePath & "\ErrorLog.txt")
        Else
            If blnStop = False AndAlso blnStopVisit = False Then bwVisitRequests.RunWorkerAsync()
            LogErrorToFile(STOPERROR, sFilePath & "\ErrorLog.txt")
            Application.DoEvents()
        End If
    End Sub

Open in new window

0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22949960
Initially started like this:
    Me.bwPatientRequests.RunWorkerAsync()
    Me.bwVisitRequests.RunWorkerAsync()
    Me.bwProcessMessages.RunWorkerAsync()

Open in new window

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 22950368
The concept seems to work for me...can you do some testing with a simple project?

This is what I get:
BGW..2
BGW.1
BGW...3
BGW.1
BGW.1
BGW.1
BGW.1
BGW..2
BGW.1
BGW.1
BGW.1
BGW.1
BGW.1
BGW..2
BGW.1
BGW...3
etc...
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        BackgroundWorker1.RunWorkerAsync()
        BackgroundWorker2.RunWorkerAsync()
        BackgroundWorker3.RunWorkerAsync()
    End Sub
 
    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Debug.Print("BGW.1")
        System.Threading.Thread.Sleep(1000)
    End Sub
 
    Private Sub BackgroundWorker2_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
        Debug.Print("BGW..2")
        System.Threading.Thread.Sleep(5000)
    End Sub
 
    Private Sub BackgroundWorker3_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker3.DoWork
        Debug.Print("BGW...3")
        System.Threading.Thread.Sleep(10000)
    End Sub
 
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        BackgroundWorker1.RunWorkerAsync()
    End Sub
 
    Private Sub BackgroundWorker2_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker2.RunWorkerCompleted
        BackgroundWorker2.RunWorkerAsync()
    End Sub
 
    Private Sub BackgroundWorker3_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker3.RunWorkerCompleted
        BackgroundWorker3.RunWorkerAsync()
    End Sub
 
End Class

Open in new window

0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22951557
We have found the problem. In one of the DoWork events, we are sending requests in a while
loop. But, even if I put another Sleep INSIDE the loop, it still fires every 2-15 seconds. Is there a way for me to make a while loop stop for a specified period of time?
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22951610
See code below...
Private Sub bwVisitRequests_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwVisitRequests.DoWork
  Try
    Dim SDATE As Object = Me.ILynxPMTableAdapter_VisitRequests.GETLASTMESSAGETIME("GETUPDATEDVISITS")
    If Me.CoSettingsTableAdapter1.GetValue("InitialVisitLoadComplete").ToUpper <> "TRUE" Then    'initial data load
        'start 1 year back and go 1 year forward
        Dim myDate As DateTime = Now.AddDays(-365)
        Dim myLastDate As String = Me.CoPracticeSettingsTableAdapter1.GetValue("InitialVisitLoadComplete").ToUpper
        If IsDate(myLastDate) Then myDate = CDate(myLastDate).AddDays(1)
   
        While myDate < Now.AddDays(365)
            ' Do the message send/receive here
            ' Now update the settings table with the date
            CoSettingsTableAdapter1.UpdateQuery(myDate.ToString("MM/dd/yyyy"), "InitialVisitLoadComplete")
            ' Sleep the thread
            System.Threading.Thread.Sleep(30000)
            ' and update the date to process next day's messages
            myDate = myDate.AddDays(1)
        End While
    Else
      ' do something else
    End If
    iVisitRequestErrorCount = 0
  Catch ex As Exception
    LogErrorToFile("Error on visit request:  " & ex.ToString, sFilePath & "\ErrorLog.txt")
    iVisitRequestErrorCount += 1
  Finally
    System.Threading.Thread.Sleep(INTERVAL_VisitRequests) ' INTERVAL_VisitRequests = 180000
  End Try
End Sub

Open in new window

0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22951624
The 30 second sleep inside the loop is not working.
Any ideas?
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22951753
Would this work?
Dim mytime As Integer = Date.Now.Second
Dim waittime As Integer = Date.Now.Second + 30000
While mytime < waittime
  mytime = Date.Now.Second
End While

Open in new window

0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22952238
Well, according to the test posted below, the way we have our code written, it *should* work.
Can you see anything in our code above that may be wrong?
I also posted the bwVisitRequests_RunWorkerCompleted below.
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.BackgroundWorker1.RunWorkerAsync()
    End Sub
 
    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        Me.BackgroundWorker1.RunWorkerAsync()
    End Sub
 
    Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        Dim mydate As DateTime = Date.Now
        Try
            Debug.Print(String.Format("mydate outside {0:F}", mydate))
            While mydate < Now.AddDays(5)
                Dim mytime As DateTime = Date.Now
                Debug.Print("mytime {0:F}", mytime)
                System.Threading.Thread.Sleep(10000)
                mydate = mydate.AddDays(1)
                Debug.Print(String.Format("mydate inside {0:F}", mydate))
            End While
        Finally
            System.Threading.Thread.Sleep(30000)
        End Try
    End Sub
End Class
 
'Results:
mydate outside Thursday, November 13, 2008 11:36:44 AM
mytime Thursday, 13 November 2008 11:36:44
mydate inside Friday, November 14, 2008 11:36:44 AM
mytime Thursday, 13 November 2008 11:36:54
mydate inside Saturday, November 15, 2008 11:36:44 AM
mytime Thursday, 13 November 2008 11:37:04
mydate inside Sunday, November 16, 2008 11:36:44 AM
mytime Thursday, 13 November 2008 11:37:14
mydate inside Monday, November 17, 2008 11:36:44 AM
mytime Thursday, 13 November 2008 11:37:24
mydate inside Tuesday, November 18, 2008 11:36:44 AM
mytime Thursday, 13 November 2008 11:37:34
mydate inside Wednesday, November 19, 2008 11:36:44 AM
' here is where the 30 second sleep occurs
mydate outside Thursday, November 13, 2008 11:38:14 AM
mytime Thursday, 13 November 2008 11:38:14
mydate inside Friday, November 14, 2008 11:38:14 AM
mytime Thursday, 13 November 2008 11:38:24
mydate inside Saturday, November 15, 2008 11:38:14 AM
mytime Thursday, 13 November 2008 11:38:34
mydate inside Sunday, November 16, 2008 11:38:14 AM
mytime Thursday, 13 November 2008 11:38:44
mydate inside Monday, November 17, 2008 11:38:14 AM
mytime Thursday, 13 November 2008 11:38:54
mydate inside Tuesday, November 18, 2008 11:38:14 AM
mytime Thursday, 13 November 2008 11:39:04
mydate inside Wednesday, November 19, 2008 11:38:14 AM
' here is where the 30 second sleep occurs
mydate outside Thursday, November 13, 2008 11:39:44 AM
 
    Private Sub bwVisitRequests_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwVisitRequests.RunWorkerCompleted
        If iVisitRequestErrorCount > 10 Then
            LogErrorToFile("MORE THAN 10 ERRORS HAVE OCCURRED ON GETUPDATEDVISIT REQUEST.  STOPPED THIS CHANNEL AT " & Now.ToString, sFilePath & "\ErrorLog.txt")
        Else
            If blnStop = False AndAlso blnStopVisit = False Then bwVisitRequests.RunWorkerAsync()
            LogErrorToFile(STOPERROR, sFilePath & "\ErrorLog.txt")
            Application.DoEvents()
        End If
    End Sub

Open in new window

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 22952908
Nothing is popping out at me...  =\

I would change this:

    While myDate < Now.AddDays(365)

To this though:

    Dim targetDT As DateTime = Now.AddDays(365)
    While myDate < targetDT
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22955893
I have found that separating the code within the DOWork, in particular the one with the While loop has made things work like we want, including sleeping within the while loop and sleeping after the while loop is done. I moved the sleep for the whole worker to the RunWorkCompleted before the RunAsync gets called again.

Things look like they work as expected, now.
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 2000 total points
ID: 22956322
"I moved the sleep for the whole worker to the RunWorkCompleted before the RunAsync gets called again."

But the RunWorkCompleted() event actually runs in the MAIN UI THREAD...so if you make it Sleep you will be locking up your Form!  =\
0
 
LVL 26

Author Comment

by:Eddie Shipman
ID: 22961659
Whoa, I didn't know that. Thanks for the heads up..
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Screencast - Getting to Know the Pipeline
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses

850 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