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:
- create
high_resolution_timer
- 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. - 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
Utc Time Resets to 2000-01-01 (Ruby). How to Prevent the Time from Resetting
Watir and Text Field Inside Iframe
Why Does Shoveling a String into a Hash Cause This Result
Definition of Method in Top Level
Ruby on Rails CSV Upload&Import - File Name Too Long
Create a Titleize Method, That Excludes "Little Words"
Bind and Destructure Block Arguments
Error Loading the 'Sqlite3' Active Record Adapter. When I Deploy in Heroku
How to Condense Summable Metrics to a Unique Identifier in a Ruby Table
How to Use 'Debugger' and 'Pry' When Developing a Gem? (Ruby)
Selenium Webdriver Take Screenshot of Viewport Only
Why Must I Explicitly Call Self on Accessor When Using the Array Union Operator |= in Ruby
Implementing Dry-Run in Ruby Script
Rails Activerecord: Saving Nested Models Is Rolled Back
Ruby/Rails - Active Record Db Migration to MySQL - Timestamp Type
Can't Find Ffi.H When Installing Ffi Ruby Gem
I Want to Return a Single Result Using .Find() with Ruby on Rails