'How to use "Threading" / Parallel methods in XAML UWP
I previously used Threading functions in WinForms but not I have a project that uses XAML.
I am working out with a simple robot that has Odometry. Right now, I am trying to implement 2 process simultaneously specifically..
Starting the Motors(forward, backward, left, right) and
Counting the encoders (number of rotations it turns or number of encoder ticks)
My problem is that after my I press the forward button (or any motor button), my UI stops and doesn't perform the StartCount() function and doesn't change my TextBoxes according to the number of ticks.
Is there any way I could thread these 2 methods? And threading in XAML UWP does not work.
Here is my code:
private void Forward_btn_Click(object sender, RoutedEventArgs e)
{
StartStop_Bool = true;
CwCcwPinLeft.Write(GpioPinValue.Low);
CwCcwPinRight.Write(GpioPinValue.High);
Task.Delay(FIFTEEN_MILLISECOND);
RunBrakePinRight.Write(GpioPinValue.High);
RunBrakePinLeft.Write(GpioPinValue.High);
StartCount();
}
Startcount() function :
private void StartCount()
{
if (TicksLeftPin.Read() == GpioPinValue.High &&
TicksRightPin.Read() == GpioPinValue.High)
{
if (CwCcwPinLeft.Read() == GpioPinValue.High &&
CwCcwPinRight.Read() == GpioPinValue.Low)
{
// MOVING ON A STRAIGHT LINE
LeftMotor_TickCounter++;
RightMotor_TickCounter++;
}
else if (CwCcwPinLeft.Read() == GpioPinValue.High &&
CwCcwPinRight.Read() == GpioPinValue.High)
{
// ROTATING TO RIGHT
LeftMotor_TickCounter++;
RightMotor_TickCounter--;
}
else if (CwCcwPinLeft.Read() == GpioPinValue.Low &&
CwCcwPinRight.Read() == GpioPinValue.High)
{
// MOVING BACKWARDS
LeftMotor_TickCounter--;
RightMotor_TickCounter--;
}
else
{
// ROTATING TO LEFT
LeftMotor_TickCounter--;
RightMotor_TickCounter++;
}
}
else if (TicksLeftPin.Read() == GpioPinValue.High &&
TicksRightPin.Read() == GpioPinValue.Low)
{
if (CwCcwPinLeft.Read() == GpioPinValue.High)
{
LeftMotor_TickCounter++;
}
else
{
LeftMotor_TickCounter--;
}
}
else if (TicksLeftPin.Read() == GpioPinValue.Low &&
TicksRightPin.Read() == GpioPinValue.High)
{
if (CwCcwPinRight.Read() == GpioPinValue.Low)
{
RightMotor_TickCounter++;
}
else
{
RightMotor_TickCounter--;
}
}
CounterLabelLeft.Text = LeftMotor_TickCounter.ToString();
CounterLabelRight.Text = RightMotor_TickCounter.ToString();
}
Solution 1:[1]
I would use async await to keep ui responsive. It will allow stuff to happen in background and the UI to stay responsive. I would change StartCount to something like this. Any function you run async you should return something. I am assuming your app is using a .net version that supports async and await
private async Task<bool> StartCount() {
if (TicksLeftPin.Read() == GpioPinValue.High && TicksRightPin.Read() == GpioPinValue.High)
{
if (CwCcwPinLeft.Read() == GpioPinValue.High && CwCcwPinRight.Read() == GpioPinValue.Low)
{ // MOVING ON A STRAIGHT LINE
LeftMotor_TickCounter++;
RightMotor_TickCounter++;
}
else if (CwCcwPinLeft.Read() == GpioPinValue.High && CwCcwPinRight.Read() == GpioPinValue.High)
{ // ROTATING TO RIGHT
LeftMotor_TickCounter++;
RightMotor_TickCounter--;
}
else if (CwCcwPinLeft.Read() == GpioPinValue.Low && CwCcwPinRight.Read() == GpioPinValue.High)
{ // MOVING BACKWARDS
LeftMotor_TickCounter--;
RightMotor_TickCounter--;
}
else
{ // ROTATING TO LEFT
LeftMotor_TickCounter--;
RightMotor_TickCounter++;
}
}
else if (TicksLeftPin.Read() == GpioPinValue.High && TicksRightPin.Read() == GpioPinValue.Low)
{
if (CwCcwPinLeft.Read() == GpioPinValue.High)
{
LeftMotor_TickCounter++;
}
else
{
LeftMotor_TickCounter--;
}
}
else if (TicksLeftPin.Read() == GpioPinValue.Low && TicksRightPin.Read() == GpioPinValue.High)
{
if (CwCcwPinRight.Read() == GpioPinValue.Low)
{
RightMotor_TickCounter++;
}
else
{
RightMotor_TickCounter--;
}
}
CounterLabelLeft.Text = LeftMotor_TickCounter.ToString();
CounterLabelRight.Text = RightMotor_TickCounter.ToString();
return true;
}
And your event handler to this. The awaits will allow the UI to update while the function is running.
private async void Forward_btn_Click(object sender, RoutedEventArgs e)
{
StartStop_Bool = true;
CwCcwPinLeft.Write(GpioPinValue.Low);
CwCcwPinRight.Write(GpioPinValue.High);
await Task.Delay(FIFTEEN_MILLISECOND);
RunBrakePinRight.Write(GpioPinValue.High);
RunBrakePinLeft.Write(GpioPinValue.High);
await StartCount();
}
Another option would be to do this in a thread and use Dispatcher.BeginInvoke when ever you update a control from the thread.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ken Tucker |
