Hi,
I am trying to build a wind speed sensor. For this I Count te amount of interrupts on a gpio pin that is configured as input in a certain time period.
At the end of this period I like to show the count value in a textbox on the UI.
…
private void InitAnemoTimer()
{
Anemotimer = new System.Threading.Timer(_ => OnAnemoTimerCallBack(),null, 0, Timer_Constante);
}
private void Windpin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs args)
{
if (args.Edge == GpioPinEdge.FallingEdge)
{
windcounter=windcounter+1; //Every windpuls increment the counter.
}
}
private void OnAnemoTimerCallBack()
{
wind = windcounter; //Calculates wind
//windBox.Text = wind.ToString(); //show in texbox: this is not working
windcounter = 0; //Reset windcounter
Anemotimer.Change(0, Timer_Constante); //restarts the timer
}
On problem is that the UI is on a different tread than the system treading timer.
How can I synchronize these treads?
-
- Posts: 6
- Joined: Fri May 15, 2015 8:47 am
Re: Synchronizing with ui tread
You can have the main thread/object (ui) register for an event and then in your gpio thread raise an event. You decide what data to pass, even an object.
Read up on RaiseEvent and AddHandler
Read up on RaiseEvent and AddHandler
-
- Posts: 1412
- Joined: Fri Jan 04, 2013 1:57 pm
- Location: de_DE
Re: Synchronizing with ui tread
you can make a call within the ui thread context, by use Windows.UI.Core.CoreDispatcher.RunAsync()
use the dispatcher of the UI element (MainPage)
use the dispatcher of the UI element (MainPage)
{ I only give negative feedback }
RPi B (256MB), B (512MB), B+, ZeroW; 2B; 3B, 3B+; 4B (4GB)
RPi B (256MB), B (512MB), B+, ZeroW; 2B; 3B, 3B+; 4B (4GB)
-
- Posts: 58
- Joined: Tue Jun 09, 2015 8:08 pm
- Contact: Website
Re: Synchronizing with ui tread
For an example bit code you want todo something like:
Code: Select all
var task = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
winBox.Text = windcounter.ToString();
});
Last edited by haroldpulcher on Mon Aug 31, 2015 4:47 pm, edited 1 time in total.
-
- Posts: 6
- Joined: Fri May 15, 2015 8:47 am
Re: Synchronizing with ui tread
Hi Haroldpulcher,
thanks for your code example.
unfortunately this is not working for the raspberry 2 on IOT. The var and Dispatcher objects are not available.
There is the CoreDispatcher class available. Maybe I can use this but I am struggling with the syntax.
I also do not see how to call this “task” from my OnAnemoTimerCallBack routine?
thanks for your code example.
unfortunately this is not working for the raspberry 2 on IOT. The var and Dispatcher objects are not available.
There is the CoreDispatcher class available. Maybe I can use this but I am struggling with the syntax.
I also do not see how to call this “task” from my OnAnemoTimerCallBack routine?
-
- Posts: 58
- Joined: Tue Jun 09, 2015 8:08 pm
- Contact: Website
Re: Synchronizing with ui tread
Try putting the keyword "this" in front of the Dispatcher.
I left that off for some reason in my example.
I left that off for some reason in my example.
-
- Posts: 58
- Joined: Tue Jun 09, 2015 8:08 pm
- Contact: Website
Re: Synchronizing with ui tread
You can also checkout a bit of code thatI am using to demo in my talks at: https://github.com/pulcher/iot-demos
Check the "pushPotBlink" solution. Not the best code, but it does work.
Check the "pushPotBlink" solution. Not the best code, but it does work.
-
- Posts: 6
- Joined: Fri May 15, 2015 8:47 am
Re: Synchronizing with ui tread
Ok, I suppose I have to do something like this:
When I do this I get the warning : Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the “Await” operator to the result of the call.
A quick fix is proposed but when I accepts that I get this:
and I get a compile error stating that the await operator can only be used within a async methode.
Code: Select all
private void OnAnemoTimerCallBack()
{
wind = windcounter; //Calculates wind
//windBox.Text = wind.ToString(); //show in texbox
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
windBox.Text = windcounter.ToString();
});
windcounter = 0; //Reset windcounter
Anemotimer.Change(0, Timer_Constante); //restarts the timer
}
A quick fix is proposed but when I accepts that I get this:
Code: Select all
private void OnAnemoTimerCallBack()
{
wind = windcounter; //Calculates wind
await
//windBox.Text = wind.ToString(); //show in texbox
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
windBox.Text = windcounter.ToString();
}); windcounter = 0; //Reset windcounter
Anemotimer.Change(0, Timer_Constante); //restarts the timer
}
-
- Posts: 6
- Joined: Fri May 15, 2015 8:47 am
Re: Synchronizing with ui tread
Got It !
thank you very much putting me on this solution. I only wish I did understand it a little bit better. 
Code: Select all
private async void OnAnemoTimerCallBack()
{
wind = windcounter; //Calculates wind
await
//windBox.Text = wind.ToString(); //show in texbox
this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
windBox.Text = windcounter.ToString();
});
windcounter = 0; //Reset windcounter
Anemotimer.Change(0, Timer_Constante); //restarts the timer
}

Re: Synchronizing with ui tread
A lot of overhead and complexity when raising an event is what you really needed.
Because in essence you are blocking your timer thread until the await is satisfied. Might or might not have repercussions from that, such as missed counts.

-
- Posts: 58
- Joined: Tue Jun 09, 2015 8:08 pm
- Contact: Website
Re: Synchronizing with ui tread
I believe it is actually the other way around.
The RunAsync command fires an event with a payload to the UI thread and returns. So you code goes merrily one.
If you were to put a "AsTask().Wait()" on the end of that, then that call will wait till the UI thread is done.
For a better explanation checkout: https://social.msdn.microsoft.com/Forum ... withcsharp
The RunAsync command fires an event with a payload to the UI thread and returns. So you code goes merrily one.
If you were to put a "AsTask().Wait()" on the end of that, then that call will wait till the UI thread is done.
For a better explanation checkout: https://social.msdn.microsoft.com/Forum ... withcsharp
Re: Synchronizing with ui tread
RunAsync doesn't fire events,
Events are less troublesome and lighter weight although what you suggest will probably solve his problem.
This is what happens on Await : https://msdn.microsoft.com/en-us/library/hh191443.aspx
I think you will find events much easier to get your head wrapped around. I use both, but async/await I use for file operation etc that might take a long time (and block the UI from getting time to run)
There are as usual multiple solutions and preferences
Events are less troublesome and lighter weight although what you suggest will probably solve his problem.
This is what happens on Await : https://msdn.microsoft.com/en-us/library/hh191443.aspx
I think you will find events much easier to get your head wrapped around. I use both, but async/await I use for file operation etc that might take a long time (and block the UI from getting time to run)
There are as usual multiple solutions and preferences

-
- Posts: 1412
- Joined: Fri Jan 04, 2013 1:57 pm
- Location: de_DE
Re: Synchronizing with ui tread
maybe that is more useful to youRobWarning wrote:Hi Haroldpulcher,
thanks for your code example.
unfortunately this is not working for the raspberry 2 on IOT.
do this in your MainPage
Code: Select all
private void Page_Loaded(object sender, RoutedEventArgs e)
{
timer = new Windows.UI.Xaml.DispatchTimer();
timer.Tick += Timer_Tick;
timer.Interval = TimeSpan.FromMilliseconds(1000.0);
timer.Start();
}
private void Timer_Tick(object sender, object e)
{
// do something in UI thread context
// e.g. polling your values you want to display on UI
}
if you use a "standalone" none-UI-thread, you can pass the Dispatcher of the UI element to your thread, to be able to access to the Dispatcher to execute/access to UI properties via RunAsync...
and by the way, nobody force you to use "RunAsync()" with "await"...
you can use it without await as well... and in that case it is not blocking the UI thread... that's because it is called async

only in case you need to lineup executions in correct order (because the result od the execution is needed for the followed execution), the easiest way to do so is using "await", but it is indeed not always the best idea then.
and "var" should be available, as long you use all needed references and usings.
GerritV wrote:You can have the main thread/object (ui) register for an event and then in your gpio thread raise an event. You decide what data to pass, even an object.
Read up on RaiseEvent and AddHandler
an event does not necessarily executes in UI thread context, in case you build your own events from within none-UI-context-threads... in that case you have to switch your execution into UI thread context first to do UI element access via one of the RunAsync calls from an UI elements Dispatcher.GerritV wrote:A lot of overhead and complexity when raising an event is what you really needed.Because in essence you are blocking your timer thread until the await is satisfied. Might or might not have repercussions from that, such as missed counts.
{ I only give negative feedback }
RPi B (256MB), B (512MB), B+, ZeroW; 2B; 3B, 3B+; 4B (4GB)
RPi B (256MB), B (512MB), B+, ZeroW; 2B; 3B, 3B+; 4B (4GB)