0

I have the following code whose purpose is to call a function at a specific time. However I get the exception when WaitTask.Start(); is called Additional information: Start may not be called on a promise-style task.

DateTime today = DateTime.Today;
DateTime twoThirtyET = today.AddHours(14.50);

Execute(CallAtTime, twoThirtyET);

public void Execute(Action action, DateTime ExecutionTime)
{
    Task WaitTask =          Task.Delay((int)ExecutionTime.Subtract(DateTime.Now).TotalMilliseconds);
    WaitTask.ContinueWith(_ => action);
    WaitTask.Start();
}

private void CallAtTime()
{
    Console.WriteLine("Called at time");
}
Ivan
  • 7,448
  • 14
  • 69
  • 134
  • 1
    Why don't you just create a console app that does what you want NOW and schedule it via Windows Scheduler or some other scheduling tool? – D Stanley Feb 17 '16 at 23:31
  • First answer that found by searching for error message https://www.bing.com/search?q=Additional+information%3A+Start+may+not+be+called+on+a+promise-style+task seem to provide almost exact code you trying to write (short of computing time that you know how to do) in both styles (`async` and `ContinueWith`) - so looks perfect duplicate. Note that as @DStanley pointed out there are better more reliable ways to achieve scheduling of tasks unless it is exactly what you want to learn. – Alexei Levenkov Feb 17 '16 at 23:35
  • To be fair, there might be scenarios where the Windows Scheduler is not appropriate. Cache invalidation is the only terrible example I can think of at the moment. – Troels Larsen Feb 17 '16 at 23:38
  • 1
    @TroelsLarsen sure. Also in most cases there would be existing solution that handles that better than custom code that may run at some point. I.e. for your sample - most caching frameworks have expiration timeouts... – Alexei Levenkov Feb 18 '16 at 00:02

3 Answers3

2

You are getting Additional information: Start may not be called on a promise-style task. because the Task from Task.Delay has already been started, take a look at this answer for further information.

The simplest change to make would be to remove the call to WaitTask.StartNew() as it is unnecessary.

Oh, and you may want to actually invoke your action in the callback rather than just returning it:

WaitTask.ContinueWith(_ => action());
Community
  • 1
  • 1
Lukazoid
  • 19,016
  • 3
  • 62
  • 85
1

You can use a timer. (2000 is the interval in milliseconds, so 2 seconds)

class Program
{
    private static System.Timers.Timer _timer;
    static void Main(string[] args)
    {
        _timer = new System.Timers.Timer(2000);
        _timer.Elapsed += timer_Elapsed;
        _timer.Start();
        Console.ReadLine();
    }

    static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        _timer.Stop(); //If you only want it to run once
        Console.WriteLine("Elapsed");
    }
}
Troels Larsen
  • 4,462
  • 2
  • 34
  • 54
-1

Full Example

namespace YourNamespace
{
    using System.Threading;

    public class MainClass
    {
        public void Main()
        {
            PostponedAction action = new PostponedAction();
            action.WaitExecute(DateTime.Today.AddHours(14.5) - DateTime.Now);
        }
    }

    public class PostponedAction
    {
        public void WaitExecute(TimeSpan waitTime)
        {
            Thread.Sleep(waitTime);
            // Do stuff
        }
    }
}
Tyler Pantuso
  • 835
  • 8
  • 16