Solved

Timer does not work during BeginInvoke

Posted on 2011-02-13
11
468 Views
Last Modified: 2012-05-11
Hi. I have a Sub that consumes some time.
it also calls a WebService so it can take few seconds or minutes.
during that time I'd like to run some Form's animation code that wakes on timer Tick.
I'm using BeginInvoke thread method to run MySub
But the timer does not tick during that time (but only after MySub is finished).
Why is that? and how can it be fixed?
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Animate_Notification_icon_Timer.Tick
	'my animation code.
    End Sub

    Friend WithEvents Animate_Notification_icon_Timer As System.Windows.Forms.Timer

    Delegate Sub InvokeDelegateMySub()

    Animate_Notification_icon_Timer.Start()
    Me.BeginInvoke(New InvokeDelegateMySub(AddressOf MySub))

Open in new window

0
Comment
Question by:tuchfeld
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
11 Comments
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 34885498
"Me.BeginInvoke"

This means, "Run the delegate on the same thread that owns this control".  The control in question here is "Me", or the FORM.  So essentially you told the delegate to run on the UI thread and is causing it to be unavailable to handle the Timer tick events.

You need create an actual thread to run it:

    Dim T As New System.Threading.Thread(AddressOf MySub)
    T.Start()

*Use Invoke/Delegates to properly update the UI when the thread completes.

Or use the BackgroundWorker() control instead:
http://msdn.microsoft.com/en-us/library/cc221403(VS.95).aspx
0
 

Author Comment

by:tuchfeld
ID: 34886650
please explain
I need to access UI also from MySub.
using thread I get Exception.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 34887732
What version VB.Net you using?
0
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 

Assisted Solution

by:tuchfeld
tuchfeld earned 0 total points
ID: 34887819
VB.Net 2
what do you think about the folowing solution?
Dim run_thread As Boolean
Sub MyAnimation()
    run_thread = True
    While run_thread
        'step animation code...
        Thread.Sleep(300)
    End While
End Sub

Dim T As Thread = New System.Threading.Thread(AddressOf MyAnimation)
T.Start()
MySub()
run_thread = False

Open in new window

0
 
LVL 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 500 total points
ID: 34888042
Animation type code should really be on the main UI thread so I'd keep it in the Timer code you showed earlier.
*Of course, I haven't seen this code...how are you "animating" the form?

The code in MySub, which uses the WebService, should be in the other thread.  Place a BackgroundWorker() control from the ToolBox (near the bottom in the 'Components' section by default) and set its WorkerReportsProgress() Property to True.

Now use the DoWork(), ProgressChanged(), and the RunWorkerCompleted() events:
Public Class Form1

    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        ' ...this is running in the other thread...

        ' ...call your WebService here...

        ' ...use BackgroundWorker1.ReportProgress() to update the GUI:
        ' http://msdn.microsoft.com/en-us/library/a3zbdb1t.aspx

        BackgroundWorker1.ReportProgress(25, "put something here to pass it: can be anything")
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        ' ...This is running in the main UI thread...
        ' ...This fires when BackgroundWorker1.ReportProgress() is used from the DoWork() handler

        ' Grab the status updates:
        Dim percentage As Integer = e.ProgressPercentage
        Dim data As String = e.UserState ' <-- cast it accordingly...you can pass ANYTHING (not just string)
        ' use that data somehow in the GUI:
        ProgressBar1.Value = percentage
        Label1.Text = data

        ' ... update the GUI in here ...
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        ' ...This is running in the main UI thread...
        ' ...This fires when the DoWork() handler has completed...

        ' ... update the GUI in here ...
    End Sub

End Class

Open in new window

0
 
LVL 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 500 total points
ID: 34888053
*You can pass things to the RunWorkerCompleted() event by setting "e.Result" in the DoWork() handler:
Public Class Form1

    Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        ' ...this is running in the other thread...

        ' ...call your WebService here...

        ' ...use BackgroundWorker1.ReportProgress() to update the GUI:
        ' http://msdn.microsoft.com/en-us/library/a3zbdb1t.aspx

        BackgroundWorker1.ReportProgress(25, "put something here to pass it: can be anything")

        e.Result = "something"
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        ' ...This is running in the main UI thread...
        ' ...This fires when BackgroundWorker1.ReportProgress() is used from the DoWork() handler

        ' Grab the status updates:
        Dim percentage As Integer = e.ProgressPercentage
        Dim data As String = e.UserState ' <-- cast it accordingly...you can pass ANYTHING (not just string)
        ' use that data somehow in the GUI:
        ProgressBar1.Value = percentage
        Label1.Text = data

        ' ... update the GUI in here ...
    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
        ' ...This is running in the main UI thread...
        ' ...This fires when the DoWork() handler has completed...

        ' ... update the GUI in here ...
        Dim result As String = e.Result
        Label1.Text = result
    End Sub

End Class

Open in new window

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 34888565
Your original description stated:

    "But the timer does not tick during that time (but only after MySub is finished)."

Which indicates that you were running MySub (with the WebService) on the main UI thread causing it to lock up and not be able to process the pending Tick() events.

Your solution of putting MyAnimation() into another thread should not work then, UNLESS you also put MySub() into another thread as per my comment here:
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_26818813.html34885498

Did you put MySub() as well into another thread?

You also asked:

    "Why is that? and how can it be fixed?"

Which I answered by explaining about threads...

Your animation consists of "switching icons in the Notification area".  Did you use Invoke/Delegates to update the UI from your thread?...or did you turn off cross-thread checking?

Anyhoo...good luck.
0
 

Author Comment

by:tuchfeld
ID: 34893032
in My specific case. I don't mind if the form is Blocked during MySub run
as long as the Notification icon is animated (icons are replcaed).
The Form is only for DEBUG mode and inactive in production.
in general I believe You are right ! but it takes some effort to implement and mess this it.
but for my specific case I think my solution "works".
don't you think?
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 34893260
"I don't mind if the form is Blocked during MySub run"

If the form is blocked then it can't update the notification icons.

That is where I'm getting confused.  Your description of the problem and your solution don't match to what I would expect to happen in this type of situation.

Not sure why your solution "works"...just trying to understand.  ;)

If it works then great!...
0
 

Author Comment

by:tuchfeld
ID: 34893291
As I posted 02/14/11 03:59 PM, ID: 34887819
MySub() keeps waiting...
and the Notification icon is animating..
just what I wanted.
Idle_Mind, I really appreciate your information here.
and as i said I might get back here to learn some more.
This, will probably happen when I'll discover that I do want Form UI in production mode.
but I find it time consuming for now to do it.
0
 

Author Closing Comment

by:tuchfeld
ID: 34932077
I keep "my" solution since it works.. for me.
the animation task is very light (switching icons in the Notification area).
Anyway Thanks for the ideas and the background..
I might visit this solution again some day...
0

Featured Post

Enroll in July's Course of the Month

July's Course of the Month is now available! Enroll to learn HTML5 and prepare for certification. It's free for Premium Members, Team Accounts, and Qualified Experts.

Question has a verified solution.

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

A while ago, I was working on a Windows Forms application and I needed a special label control with reflection (glass) effect to show some titles in a stylish way. I've always enjoyed working with graphics, but it's never too clever to re-invent …
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses

617 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