Solved

Timer does not work during BeginInvoke

Posted on 2011-02-13
11
464 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
 

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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

743 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

12 Experts available now in Live!

Get 1:1 Help Now