How to Schedule a Function to Execute at a Future Time

How to schedule an operation to run at future time

You can use boost::asio::high_resolution_timer with its async_wait method.

Every time when you want to schedule the operation of pushing task into queue you have to:

  1. create high_resolution_timer
  2. call expires_after which specifies the expiry time (SLEEP_TIME_MS) i.e. when handler is called. In your case in this handler you push a task into the queue.
  3. call async_wait with your handler

If we assume that execute method returns bool which indicates whether a task is completed (all phases were executed), it may be rewritten into sth like this:

     while (!m_queue.empty()) // this condition should be changed
{
Task* task = m_queue.pop();
bool finished = task->execute();
if (!finished)
scheduler works here - start async_wait with handler
}

If I understand correctly, you want to push task into queue when SLEEP_TIME_MS is expired, so you cannot break loop when queue is empty, because you have to wait until pending tasks will be completion. You can introduce stop flag. And break loop on demand.


Below I put a snippet of code which works in the way you described (I hope):

struct Scheduler {
Scheduler(boost::asio::io_context& io)
: io(io) {}

boost::asio::io_context& io;

template<class F>
void schedule (F&& handler) {
auto timer = std::make_shared<boost::asio::high_resolution_timer>(io);
timer->expires_after(std::chrono::milliseconds(5000)); // SLEEP_TIME_MS
timer->async_wait(
[timer,handler](const boost::system::error_code& ec) {
handler();
});
}
};

struct Task {
int phase = -1;

bool execute() {
++phase;
std::cout << "phase: " << phase << std::endl;
if (phase == 0) {
return false;
}
else {

}
return true;
}
};

struct TaskManager {
Scheduler s;
std::queue<std::shared_ptr<Task>> tasks;
std::mutex tasksMtx;
std::atomic<bool> stop{false};

TaskManager(boost::asio::io_context& io) : s(io) {
for (int i = 0; i < 5; ++i)
tasks.push(std::make_shared<Task>());
}

void run() {
while (true) {
if (stop)
break;

{
std::lock_guard<std::mutex> lock{tasksMtx};
if (tasks.empty())
continue;
}

std::shared_ptr<Task> currTask = tasks.front();
tasks.pop();

bool finished = currTask->execute();
if (!finished)
s.schedule( [this, currTask](){ insertTaskToVector(std::move(currTask)); } );
}
}

template<class T>
void insertTaskToVector(T&& t) {
std::lock_guard<std::mutex> lock{tasksMtx};
tasks.push(std::forward<T>(t));
}
};

int main() {
boost::asio::io_context io;
boost::asio::io_context::work work{io};
std::thread th([&io](){ io.run();});
TaskManager tm(io);
tm.run();

How to schedule a function to execute at a future time?

With DelayedJob you can do something like

  def in_the_future
# Some other code
end
handle_asynchronously :in_the_future, :run_at => Proc.new { 10.hours.from_now }

Very nice? :) I suggest you read the documentation as linked by jared

How to dynamically schedule a function to run at specified time

you may check existing cron like packages

https://www.npmjs.com/package/node-cron

https://www.npmjs.com/package/cron

Start a Function at Given Time

Reading the docs from http://docs.python.org/py3k/library/sched.html:

Going from that we need to work out a delay (in seconds)...

from datetime import datetime
now = datetime.now()

Then use datetime.strptime to parse '2012-07-17 15:50:00' (I'll leave the format string to you)

# I'm just creating a datetime in 3 hours... (you'd use output from above)
from datetime import timedelta
run_at = now + timedelta(hours=3)
delay = (run_at - now).total_seconds()

You can then use delay to pass into a threading.Timer instance, eg:

threading.Timer(delay, self.update).start()

How to call a method daily, at specific time, in C#?

  • Create a console app that does what you're looking for
  • Use the Windows "Scheduled Tasks" functionality to have that console app executed at the time you need it to run

That's really all you need!

Update: if you want to do this inside your app, you have several options:

  • in a Windows Forms app, you could tap into the Application.Idle event and check to see whether you've reached the time in the day to call your method. This method is only called when your app isn't busy with other stuff. A quick check to see if your target time has been reached shouldn't put too much stress on your app, I think...
  • in a ASP.NET web app, there are methods to "simulate" sending out scheduled events - check out this CodeProject article
  • and of course, you can also just simply "roll your own" in any .NET app - check out this CodeProject article for a sample implementation

Update #2: if you want to check every 60 minutes, you could create a timer that wakes up every 60 minutes and if the time is up, it calls the method.

Something like this:

using System.Timers;

const double interval60Minutes = 60 * 60 * 1000; // milliseconds to one hour

Timer checkForTime = new Timer(interval60Minutes);
checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed);
checkForTime.Enabled = true;

and then in your event handler:

void checkForTime_Elapsed(object sender, ElapsedEventArgs e)
{
if (timeIsReady())
{
SendEmail();
}
}


Related Topics



Leave a reply



Submit