Solved

Timer does not work during BeginInvoke

Posted on 2011-02-13
11
465 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
  • 6
  • 5
11 Comments
 
LVL 85

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 85

Expert Comment

by:Mike Tomlinson
ID: 34887732
What version VB.Net you using?
0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

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 85

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 85

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 85

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 85

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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

This tutorial demonstrates one way to create an application that runs without any Forms but still has a GUI presence via an Icon in the System Tray. The magic lies in Inheriting from the ApplicationContext Class and passing that to Application.Ru…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Windows 10 is mostly good. However the one thing that annoys me is how many clicks you have to do to dial a VPN connection. You have to go to settings from the start menu, (2 clicks), Network and Internet (1 click), Click VPN (another click) then fi…
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…

816 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now