Reputation: 41
Me and my friends are working on a school project where we want to make it write stuff on paper. We are programming it using c# in visual studio.
The problem we have is that it does the commands in wrong order. If we want to make it go forward and then turn it will try to do both at the same time. We have used Task.Delay to fix this problem but the code has gotten really messy and it's annoying to try to find the exact time for the delays.
Does anyone know any other way to fix this? The code below shows a little of how we have been doing things.
public static async void Go(Brick brick, uint duration, bool forward)//Makes it go forward
{
if (!forward)
{
await brick.DirectCommand.TurnMotorAtSpeedForTimeAsync(OutputPort.B | OutputPort.C, -speed, duration, true);
Console.WriteLine("Going backwards");
}
else
{
await brick.DirectCommand.TurnMotorAtSpeedForTimeAsync(OutputPort.B | OutputPort.C, speed, duration, true);
Console.WriteLine("Going forward");
}
}
public static async void Turn(Brick brick,float degrees, bool Clockwise)//Turns the robot. If it goes over for exampel 90 degrees it turns back a little
{
int direction;
int speed = 4;
degrees = Math.Abs(degrees);
DateTime start = DateTime.Now;
if (Clockwise)
{
direction = 1;
}
else
{
direction = -1;
}
float startposition = brick.Ports[InputPort.Two].SIValue;
await brick.DirectCommand.TurnMotorAtSpeedAsync(OutputPort.B, speed * direction);
await brick.DirectCommand.TurnMotorAtSpeedAsync(OutputPort.C, -speed * direction);
bool loopar = true;
while (loopar)
{
float DeltaPosition = Math.Abs(brick.Ports[InputPort.Two].SIValue - startposition);
if (DeltaPosition >= degrees)
{
await brick.DirectCommand.TurnMotorAtSpeedAsync(OutputPort.B | OutputPort.C, 0);
loopar = false;
}
//await Task.Delay(1);
Console.WriteLine(DeltaPosition);
}
loopar = true;
await Task.Delay(100);
await brick.DirectCommand.TurnMotorAtSpeedAsync(OutputPort.B, -1 * direction);
await brick.DirectCommand.TurnMotorAtSpeedAsync(OutputPort.C, 1 * direction);
while (loopar)
{
float DeltaPosition = Math.Abs(brick.Ports[InputPort.Two].SIValue - startposition);
if (DeltaPosition <= degrees)
{
await brick.DirectCommand.TurnMotorAtSpeedAsync(OutputPort.B | OutputPort.C, 0);
loopar = false;
}
Console.WriteLine(DeltaPosition);
}
TimeSpan span = DateTime.Now - start;
Console.WriteLine(span);
}
public static async void L(Brick brick)
{
Go(brick, 1000, true);
await Task.Delay(1000);
Up(brick);
await Task.Delay(500);
Turn(brick, 90, false);
await Task.Delay(5000);
Down(brick);
await Task.Delay(500);
Go(brick, 500, true);
}
As i said we dont want to use Task.Delay, but thats only solution we have right now.
Thanks in advance!
Upvotes: 2
Views: 481
Reputation: 3037
async void
is async but not awaitable. All those calls will execute whenever they feel like it.
Make them async Task
like this:
// public static async void Go(Brick brick, uint duration, bool forward)
public static async Task Go(Brick brick, uint duration, bool forward)
and then await the calls:
public static async void L(Brick brick)
{
await Go(brick, 1000, true);
await Up(brick);
await Turn(brick, 90, false);
await Down(brick);
await Go(brick, 500, true);
}
The L()
method should probably be an async Task
too, there is not enough info here to tell.
In general, async void
is dangerous and should be avoided unless you are very sure about what you are doing.
Upvotes: 5