'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.

https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.begininvoke(v=vs.110).aspx

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