Search code examples
c#timerdelegates

how to user parametrized method in TimerCallback C#


I'm Trying To create Multiple Timers to run at the same time, So I created List. I want all the timers to run the same function but with different parameters.

private void reporting()
        {
            try
            {
               for (int i = 0; i < timers.Count; i++)
                {
                    timers[i] = new Timer(new TimerCallback(Task(i)));
                    //Set the Default Time.
                    DateTime scheduledTime = DateTime.MinValue;


                        //Set the Scheduled Time by adding the Interval to Current Time.

                        scheduledTime = DateTime.Now.AddMinutes(2);
                        if (DateTime.Now > scheduledTime)
                        {
                            //If Scheduled Time is passed set Schedule for the next Interval.
                            scheduledTime = scheduledTime.AddMinutes(2);
              
                    TimeSpan TimeSpan = scheduledTime.Subtract(DateTime.Now);

                    int dueTime = Convert.ToInt32(TimeSpan.TotalMilliseconds);

                    //Change the Timer's Due Time.
                    timers[i].Change(dueTime, Timeout.Infinite);

                }
            }
            catch (Exception ex)
            {
                
            }
        }

here is the method I want to call

 private void Task(int index)
        {
            this.WriteToFile("*************"+ScheduleReport[index].Name+" Started*****************");

            this.WriteToFile("*************"+ScheduleReport[index].Name+" Finished successfully {0}*****************");
        }

and this code gives me an error in this line

timers[i] = new Timer(new TimerCallback(Task(i)));

method name Expected


Solution

  • TimerCallback expects a function that accepts one parameter of type object and returns void.

    You are currently invoking the Task(int) method, effectively trying to pass void to TimerCallback, which clearly is not valid.

    You need to wrap the invocation of Task(int) in another function, who's signature complies with the TimerCallback delegate i.e. create a closure.

    One way way to achieve this would be via a local function:

    void InvokeTaskWithIndex(object _) => Task(i);
    timers[i] = new Timer(new TimerCallback(InvokeTaskWithIndex));
    

    But a lambda expression would be more concise:

    timers[i] = new Timer(new TimerCallback(_ => Task(i)));
    

    And you don't even need to manually construct a TimerCallback instance, because lambda expressions are implicitly convertible to delegates:

    timers[i] = new Timer(_ => Task(i));