Home > Net >  count for loop iteration and do something
count for loop iteration and do something

Time:04-06

iam looking for a counter there count my iteration in a for loop.

So it should try my function minimum 5 times, and if my function is unsuccessful, it should skip the part after 5 attempts and start the next task.

How can i count this part and set it to a max lifetime from 5 iterations?

i tried already to add a Stopwatch but this only counts the time and not the iterations.

for (int i = 0; i < 5; i  )
{
    try
    {
        token.ThrowIfCancellationRequested();
        await Task.Delay(100, token);
        lbStatus.Invoke((MethodInvoker)(() => lbStatus.Text = "Search Portal..."));

        float threshold = 0.7f;
        var enemyTemplate =
            new Image<Bgr, byte>(resourceFolder   "/portalenter.png");
        var enemyMask =
            new Image<Bgr, byte>(resourceFolder   "/portalentermask.png");

        Point myPosition = new Point(150, 128);
        Point screenResolution = new Point(1920, 1080);

        // Main program loop
        var enemyDetector = new EnemyDetector(enemyTemplate, enemyMask, threshold);
        var screenPrinter = new PrintScreen();

        screenPrinter.CaptureScreenToFile("screen.png", ImageFormat.Png);
        var screenCapture = new Image<Bgr, byte>("screen.png");
        var enemy = enemyDetector.GetClosestEnemy(screenCapture);
        if (enemy.HasValue)
        {
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
            CvInvoke.Rectangle(screenCapture,
                new Rectangle(new Point(enemy.Value.X, enemy.Value.Y), enemyTemplate.Size),
                new MCvScalar(255));
            var inputSimulator = new InputSimulator();
            double x1 = 963f / myPosition.X;
            double y1 = 551f / myPosition.Y;
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
            var x2 = x1 * enemy.Value.X;
            var y2 = y1 * enemy.Value.Y;
            if (x2 <= 963)
                x2 = x2 * 0.68f;
            else
                x2 = x2 * 1.38f;
            if (y2 <= 551)
                y2 = y2 * 0.68;
            else
                y2 = y2 * 1.38;
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
            var absolutePositions = PixelToAbsolute(x2, y2, screenResolution);
            inputSimulator.Mouse.MoveMouseTo(absolutePositions.Item1, absolutePositions.Item2);
            au3.Send("{G}");
            if (txtLEFT.Text == "LEFT")
            {
                inputSimulator.Mouse.LeftButtonClick();
            }
            else
            {
                inputSimulator.Mouse.RightButtonClick();
            }

            au3.Send("{G}");
            Thread.Sleep(1000);
            if (txtLEFT.Text == "LEFT")
            {
                inputSimulator.Mouse.LeftButtonClick();
            }
            else
            {
                inputSimulator.Mouse.RightButtonClick();
            }

            au3.Send("{G}");
            Thread.Sleep(1000);

            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
        }
        else
        {
            /// DO SOMETHING AFTER 5 iterations
            cts.Cancel();
            lbStatus.Invoke((MethodInvoker)(() => lbStatus.Text = "Portal not found! Restart..."));

            var t13 = Task.Run(() => Exit2(token));
            await Task.WhenAny(new[] { t13 });
        }
    }
    catch (AggregateException)
    {
        Console.WriteLine("Expected");
    }
    catch (ObjectDisposedException)
    {
        Console.WriteLine("Bug");
    }
    catch
    {
    }
}

CodePudding user response:

Do you mean to run some code and if it fails, retry, but max. 5 times? You can do it this way:

for (int i = 5; i > 0; i--) {
    try {
        doSomething();
        break; // Break if successful.
    } catch (Exception e) {
        // TODO Print the exception, etc.
        Thread.Sleep(1000); // Delay the next iteration.

        // Optional: Rethrow if it is the last iteration.
        if (i == 0) {
            throw e;
        }
    }
}

You can replace the doSomething(); line with the actual code or call a (private) method that performs that operation. The latter is usually preferred, since you separate the looping construct from the actual code.

Note that the break is placed after the work. Therefore, if the doSomething() fails, it skips the break; line and goes directly to the catch (and then to the next iteration). If it succeeds, it breaks out from the loop.

CodePudding user response:

I would use a while loop instead. Increase a counter if it failed and then exit if successful or failed too many times

int n = 0;
bool success = false;

do
{
    //Do something
    if(failed)
    {
        n  ;
    }
    else
    {
        success = true;
    }
} while (n < 5 || !success);

CodePudding user response:

You could use an if statement for anything before 5 iterations and then the other after the fifth iteration.

for (int i = 0; i <= 5; i  ) {
     try {
          if (i < 5) {
              // DO EVERYTHING YOU WANT BEFORE 5 ITERATIONS
          } else {
              // DO EVERYTHING AFTER 5
          }
     }
     catch { }
}

CodePudding user response:

I'll ignore most of your code as I'm not sure it's relevant to the problem. You're running something 5 times using a for loop.

I'd suggest you set a flag if it's successful and then check after that loop has completed as to whether you need to run your compensating action:

var success = false;

for (var i = 0; i < 5; i  )
{
    try
    { 
        // your code here
        // if completed, set success and break out of loop
        success = true;
        break;
    }
    catch 
    { 
        // your error handling here
    }
}

if (success == false)
{
    // this code executes if action failed after 5 attempts
}

  •  Tags:  
  • c#
  • Related