4

I want to do a method that will replace this-

 for (var i = 0; i < seconds; i++)
        {
            ...... // code that should run every second 

            Thread.Sleep(1000);
        }

So I wrote the following method:

  public static void DoEverySecond(int seconds, Action action)
    {
        for (var i = 0; i < seconds; i++)
        {
            action.Invoke();
            Thread.Sleep(1000);
        }
    }

and now every time that I want to do something every second I can just call -

 HelperClass.DoEverySecond(5, () =>
        {
            Console.Write("Hellow")
        });

the problem is that when the action contains return, the loop doesn't stop. It's just getting out from the action and continues to the next iteration.

  HelperClass.DoEverySecond(5, () =>
        {
              return;
        });
Andy Johnson
  • 7,938
  • 4
  • 33
  • 50
Erez
  • 6,405
  • 14
  • 70
  • 124

3 Answers3

4

Have you considered Func instead of Action and then change your code to something like:

  public static void DoEverySecond(int seconds, Func<bool> action)
    {
        for (var i = 0; i < seconds; i++)
        {
            if(!action.Invoke())
            {
                return;
            }
            Thread.Sleep(1000);
        }
    }

And then have your function return false if your loop should break

userx
  • 3,769
  • 1
  • 23
  • 33
  • Thanks userx. But I would like that the DoEverySecond method will accept any kind of code and not only with Boolean return. This reduces the method generically. – Erez Jun 15 '11 at 09:22
1

I prefer @userx's solution.

However, another option would be to throw an exception inside the invoked action when you want to exit the loop. Catch the exception in DoEverySecond and break out of the loop. Be aware of the performance implications of doing this if it is a common occurrence.

Community
  • 1
  • 1
Andy Johnson
  • 7,938
  • 4
  • 33
  • 50
  • I hate to say it (because it certainly can be expensive), but this is probably more the ".NET way" to implement it (e.g. define a custom exception like 'BreakDoEverySecondException' and catch only that exception in DoEverySecond), almost like a TimeoutException. – userx Jun 15 '11 at 09:23
0

Problem is not in the c#, but in your code.
Of course, them the action returns, next lines of code woudn't execute. You should rewrite your code to no use of return statement:

    HelperClass.DoEverySecond(5, () =>
    {
        bool notReturn = true;
        // some code to define, return or not
        if (notReturn)
        // some other code here
    });
VMAtm
  • 27,943
  • 17
  • 79
  • 125
  • 1
    What's the point of having an `if()` statement with an expression which always evaluates to true? – Igor Korkhov Jun 15 '11 at 15:06
  • It's not always evaluates to true. Get some imagination. I meant that the `notReturn` variable defines, are we continue method execution or not. I've updated the answer – VMAtm Jun 15 '11 at 16:43