Pass a bool Foo(params[]) as method Argument
Asked Answered
G

3

6

There are times that a method needs to be run several times until it validates. In my case there are expressions like bar.Name.Equals("John Doe") which I want to run and run until this expression validates.

Something like:

bool succeeded = TryUntillOk(bar.Name.Equals("John Doe"), 15, 100);

where TryUntillOk would be a method that runs this expression 15 times with a sleep of 100ms between each call.

I read this excellent list of answers to similar issues but in my case there is no standar delegate that this TryUntillOk method would accept.

The title of the question is not constructive. Feel free to edit it :)

Grisby answered 24/5, 2012 at 7:22 Comment(2)
Would this be running in a separate thread? Otherwise there's not going to be any chance for the value to change.Gridley
@GeorgeDuckett YES. Sorry for not mentioning it.Grisby
J
8

You are probably looking for something like this:

bool TryRepeatedly(Func<bool> condition, int maxRepeats, TimeSpan repeatInterval)
{
    for (var i = 0; i < maxRepeats; ++i)
    {
        if (condition()) return true;
        Thread.Sleep(repeatInterval); // or your choice of waiting mechanism
    }
    return false;
}

Which would be invoked as follows:

bool succeeded = TryRepeatedly(() => bar.Name.Equals("John Doe"),
                               15,
                               TimeSpan.FromMilliseconds(100));

The only interesting part here is that you specify the condition as a Func<bool>, which is a delegate to a method that takes no parameters and returns a boolean. Lambda expression syntax allows you to trivially construct such a delegate at the call site.

Jeavons answered 24/5, 2012 at 7:32 Comment(2)
It should probably be noted that this relies on something external (separate thread etc) causing the condition to eventually evaluate to true.Gridley
@GeorgeDuckett sorry for not mentioning this. All this would be done in worker threadsGrisby
P
1

You have to adapt the invokation. @Jon's answer has lambda invoaction, this version separates the comparand from the delegate

using System;
using System.Threading;

namespace test
{
    class something
    {
        public String Name;
    }

    class Program
    {
        private delegate bool TryableFunction(String s);

        private static bool TryUntillOk(TryableFunction f, String s, int howoften, int sleepms)
        {
            while (howoften-->0)
            {
                if (f(s)) return true;
                Thread.Sleep(sleepms);
            }
            return false;
        }

        static void Main(string[] args)
        {
            something bar=new something();

            bar.Name="Jane Doe";
            bool succeeded = TryUntillOk(bar.Name.Equals,"John Doe", 15, 100);
            Console.WriteLine("Succeeded with '{0}': {1}",bar.Name,succeeded);

            bar.Name="John Doe";
            succeeded = TryUntillOk(bar.Name.Equals,"John Doe", 15, 100);
            Console.WriteLine("Succeeded with '{0}': {1}",bar.Name,succeeded);
        }


    }
}
Paregoric answered 24/5, 2012 at 7:42 Comment(1)
Exactly this was my first attempt. Later I realized that there might be several methods to call, meaning that I'd had to declare so many delegates which is something I want to avoid.Grisby
S
0

You can check it

delegate void d_name(string s);

d_name obj =new d_name(bar.Name.Equals);

bool succeeded = TryUntillOk(obj("John Doe"), 15, 100);

TryUntillOk(obj d,type parameter2,type parameter3 )
{
  //do your work
}  
Strategist answered 24/5, 2012 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.