Davide Floriani
Davide Floriani

Reputation: 11

Await a value change in c#

I'm currently working on a project that involve a stepper motor using c# forms and arduino. I need to know in c# when the motor stops his movement. To do that, I programmed arduino to send a string trough Serial when the movement is finished. Then the string is interpreted by c# so that the app can do other things after that. I now want to have the same result as the example below, but using async await.

I stored the information that the motor stopped in:

movimentFinished = true;

I solved the problem in a terrible way using: while(movimentFinished = false){await Task.Delay(1)} The difference between a while loop and an await is going to effect other stuff on my WinApp. The while blocks all the application until movimentFinished == true;

The logic that I want is simple:

MoveMotor();

await "value change"

//do stuff after it finishes

Any help/tip to do that? Thank you for reading

//this funcion will receive an array from arduino as a reply
private void risposta(object sender, SerialDataReceivedEventArgs e)
        {
            riceved = port.ReadLine();
            rispos = riceved;
            this.Invoke(new EventHandler(Reply));
        }

//this function will run every time a reply is sent from arduino through serial
private void Reply(object sender, EventArgs e)
        {
            //string risposValore = rispos.Substring(2, rispos.Length - 2);
            char[] pcr = rispos.ToCharArray();
            rispos = rispos.Trim();
 
            if (pcr[0] == 'M' && pcr[1] == 'F' && pcr[2] == '1')
            {
                movementFinished = true;
            }
         }


//this funcion will send a serial command to arduino to run the motor
public void MoveTheMotor(int position)
        {
            int command = 1000;
            int movement = command + (position)
            string com1 = movement.ToString();
            port.Write(com1 + "\n");
            movementFinished = false;
        }


private async void Demo()
        {
            MoveTheMotor(800);

            //this while blocks everything until the value is true

            while (movementFinished == false) { await Task.Delay(1); }

            //do something after the motor finished
        }

Upvotes: 1

Views: 1877

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456437

Instead of using a boolean, you need a signal. In the blocking world, this would be a ManualResetEventSlim or similar. In the asynchronous world, this would be some form of TaskCompletionSource. As such:

private TaskCompletionSource movementFinished;

private void Reply(object sender, EventArgs e)
{
  ...
  if (pcr[0] == 'M' && pcr[1] == 'F' && pcr[2] == '1')
  {
    movementFinished.TrySetResult();
  }
}

public void MoveTheMotor(int position)
{
  ...
  movementFinished = new TaskCompletionSource();
}

private async void Demo()
{
  MoveTheMotor(800);

  await movementFinished.Task;

  //do something after the motor finished
}

Upvotes: 3

Related Questions