-
Feb 7th, 2013, 06:15 AM
#1
Thread Starter
Fanatic Member
[RESOLVED] Threading & Accessing controls repeatidly.
Hi, Whats the best way to handle updating the UI lots of times from a worker thread. Depending on speed the UI may need updating 3/4 times in a second. Say if the overall task takes 1 minute to complete, we could have over 100 updates in that given time.
My problem is it feels like i am creating a worker thread just to constantly jump back to the UI thread.
do you think the SynchronizationContext class would be better suited then what i am doing below.
vb Code:
Public Class MainForm
Private Event SomeThingChnaged As EventHandler(Of SomeThingChnagedEventArghs)
Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartButton.Click
Dim t As New System.Threading.Thread(AddressOf DoWork)
t.Start()
End Sub
Private Sub DoWork()
' Do work
RaiseEvent SomeThingChnaged(Me, New SomeThingChnagedEventArghs("Data"))
'do work
RaiseEvent SomeThingChnaged(Me, New SomeThingChnagedEventArghs("Data"))
' and so on
End Sub
Private Sub UpdateInterface(ByVal sender As Object, ByVal e As EventArgs) Handles Me.SomeThingChnaged
If Me.StatusTextBox.InvokeRequired Then
Me.StatusTextBox.Invoke(New Action(Of Object, EventArgs)(AddressOf UpdateInterface), sender, e)
Else
Dim value As String = DirectCast(sender, SomeThingChnagedEventArghs).Value
Me.StatusTextBox.AppendText(value & vbNewLine)
End If
End Sub
End Class
-
Feb 7th, 2013, 06:35 AM
#2
Re: Threading & Accessing controls repeatidly.
Invoking back to the UI 3 or 4 times a second will be fine. If you want to get rid of some of the boilerplate you could look at using a BackgroundWorker instead of an explicit Thread, though you'll have some new boilerplate associated with the BGW, but at least you can get rid of the Invoke code. SychronisationContext won't help much because you still need to Post or Send, what you've got does basically the same thing (I haven't checked, but I'd bet that it actually uses the SynchronisationContext under the hood).
Another point about the BGW is that I believe it'll use a thread from the ThreadPool, but since you're talking about a single thread that will run for a minute or so, the overhead of creating your own Thread is negligible to the point of non-existence.
-
Feb 7th, 2013, 08:21 AM
#3
Re: Threading & Accessing controls repeatidly.
You might want to consider using BeginInvoke instead of Invoke. This way your background code doesn't have to wait for your foreground updates. This is assuming you don't need strict synchronization between threads.
-
Feb 7th, 2013, 09:02 AM
#4
Thread Starter
Fanatic Member
Re: Threading & Accessing controls repeatidly.
Originally Posted by Evil_Giraffe
Invoking back to the UI 3 or 4 times a second will be fine. If you want to get rid of some of the boilerplate you could look at using a BackgroundWorker instead of an explicit Thread, though you'll have some new boilerplate associated with the BGW, but at least you can get rid of the Invoke code. SychronisationContext won't help much because you still need to Post or Send, what you've got does basically the same thing (I haven't checked, but I'd bet that it actually uses the SynchronisationContext under the hood).
Another point about the BGW is that I believe it'll use a thread from the ThreadPool, but since you're talking about a single thread that will run for a minute or so, the overhead of creating your own Thread is negligible to the point of non-existence.
so if it uses SynchronisationContext under the hood is it not best to just use it?
This is assuming you don't need strict synchronization between threads.
sorry not following this bit? But noted on begin invoke.
-
Feb 7th, 2013, 09:28 AM
#5
Re: Threading & Accessing controls repeatidly.
Originally Posted by kayleigh
so if it uses SynchronisationContext under the hood is it not best to just use it?
I would say not. The various Invoke methods on controls provide a simpler interface for invoking updates to the UI from background threads.
-
Feb 7th, 2013, 09:44 AM
#6
Thread Starter
Fanatic Member
Re: Threading & Accessing controls repeatidly.
Well thats my worry resolved
Code:
Private Sub UpdateInterface(ByVal sender As Object, ByVal e As EventArgs) Handles Me.SomeThingChnaged
If Me.StatusTextBox.InvokeRequired Then
Me.StatusTextBox.Invoke(New Action(Of Object, EventArgs)(AddressOf UpdateInterface), sender, e)
Quick note on the invoke though. Am i using the action delegate correctly since i am passing a custom event(Of T
-
Feb 7th, 2013, 11:58 AM
#7
Re: Threading & Accessing controls repeatidly.
One thing you might consider is pooling changes, if that's possible. While it might be fine to update a UI 3-4 times a second, the result is a UI that is jumping around spastically.
My usual boring signature: Nothing
-
Feb 7th, 2013, 12:26 PM
#8
Hyperactive Member
Re: Threading & Accessing controls repeatidly.
Originally Posted by kayleigh
Well thats my worry resolved
Code:
Private Sub UpdateInterface(ByVal sender As Object, ByVal e As EventArgs) Handles Me.SomeThingChnaged
If Me.StatusTextBox.InvokeRequired Then
Me.StatusTextBox.Invoke(New Action(Of Object, EventArgs)(AddressOf UpdateInterface), sender, e)
Quick note on the invoke though. Am i using the action delegate correctly since i am passing a custom event(Of T
There is nothing wrong with the use of the action delegate, you could just as easily use a anonymous method, but that is mostly up to the programmer.
Does that code execute? I would have to look it up, but I thought Invoke took and array of objects rather than multiple parameters like you have defined, but like I said, I would have to look at msdn again to make sure.
-
Feb 7th, 2013, 03:18 PM
#9
Re: Threading & Accessing controls repeatidly.
Originally Posted by wakawaka
I would have to look it up, but I thought Invoke took and array of objects rather than multiple parameters like you have defined, but like I said, I would have to look at msdn again to make sure.
Yes it does take an array but the parameter's declaration in the .Net Framework's source code was preceded by the ParamArray(or its C# equivalent if it was written in C#) keyword which tells the compiler to treat that argument and every argument after it as elements of the array itself.
-
Feb 7th, 2013, 04:21 PM
#10
Re: Threading & Accessing controls repeatidly.
Originally Posted by Evil_Giraffe
(I haven't checked, but I'd bet that it actually uses the SynchronisationContext under the hood).
vbnet Code:
Private Sub InvokeMarshaledCallback(ByVal tme As ThreadMethodEntry) If (Not tme.executionContext Is Nothing) Then If (Control.invokeMarshaledCallbackHelperDelegate Is Nothing) Then Control.invokeMarshaledCallbackHelperDelegate = New ContextCallback(AddressOf Control.InvokeMarshaledCallbackHelper) End If If (SynchronizationContext.Current Is Nothing) Then WindowsFormsSynchronizationContext.InstallIfNeeded End If tme.syncContext = SynchronizationContext.Current ExecutionContext.Run(tme.executionContext, Control.invokeMarshaledCallbackHelperDelegate, tme) Else Control.InvokeMarshaledCallbackHelper(tme) End If End Sub
Calling Invoke ultimately leads to the function above inside the Control class so yes it does use the SynchronizationContext class. Although it doesn't actually use it here, I doubt we would be seeing it here if it wasn't part of the process. This is so complex though, I'm having a hard time finding where it actually uses it. The call chains involved in an Invoke is frighteningly deep.
Last edited by Niya; Feb 7th, 2013 at 04:26 PM.
-
Feb 8th, 2013, 04:05 AM
#11
Thread Starter
Fanatic Member
Re: Threading & Accessing controls repeatidly.
Originally Posted by Shaggy Hiker
One thing you might consider is pooling changes, if that's possible. While it might be fine to update a UI 3-4 times a second, the result is a UI that is jumping around spastically.
Can you explain this please
Nya how do you guys get to the "bottom" code if that make sense. Like seeing under the hood. ty
-
Feb 8th, 2013, 04:19 AM
#12
Re: Threading & Accessing controls repeatidly.
Originally Posted by kayleigh
Can you explain this please
What SH meant is that if the UI is changing every .25s due to updates from background processing, the user could get confused. However, since you're just appending some text, it's not really going to be a problem in this case.
-
Feb 8th, 2013, 04:42 AM
#13
Thread Starter
Fanatic Member
Re: Threading & Accessing controls repeatidly.
Ahhh. TY Evil_Giraffe, One last question. Is there a reason to not use SynchronizationContext over the way iv chosen? I seem to be drawn to using SynchronizationContext, dont know why.
-
Feb 8th, 2013, 04:55 AM
#14
Re: Threading & Accessing controls repeatidly.
Because it's a more primitive abstraction. You aren't trying to synchronise threads, you're trying to update the UI from a background thread. WinForms provides an abstraction that does exactly what you want, so why would you want to go a level lower and use the primitives to re-code exactly what WinForms provides, except with the added excitement of probably making a subtle error that means your program doesn't work sometimes? (And given that this is a threading construct, by "sometimes" you can be sure that doesn't include ever in your development environment, only when your users are using it.)
-
Feb 8th, 2013, 05:01 AM
#15
Thread Starter
Fanatic Member
Re: Threading & Accessing controls repeatidly.
Sorted. Thanks every One xx
-
Feb 8th, 2013, 05:45 AM
#16
Re: Threading & Accessing controls repeatidly.
Originally Posted by kayleigh
Nya how do you guys get to the "bottom" code if that make sense. Like seeing under the hood. ty
.Net Reflector and an insane determination to dig through call chains.
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
|