Reputation: 11
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
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