创建一个异步方法,该方法在指定的时间后抛出异常,除非在该函数之外满足特定条件
Creating an async method which throws an exception after a specified amount of time unless a certain condition is met outside of that function
我目前正在编写一个 Ruby 脚本,该脚本应该在相当长的主机列表上执行不同的任务。我正在使用 net-ssh gem 与这些主机建立连接。问题是,似乎存在某些情况下 net-ssh 超时而不会抛出异常。据了解,该脚本只能完成一次 运行。大多数时候,脚本只是在某个时刻挂起而不会抛出异常或执行任何操作。
我考虑过 运行在不同的线程中设置所有可能超时的任务,向它们传递一个指向某个变量的指针,当任务成功完成时它们可以更改,然后在给定的时间内检查该变量.如果到那时任务还没有完成,在主线程中抛出异常,我可以在某个地方捕获。
这是我第一次在Ruby写东西。为了清楚地展示我想要完成的事情,这就是我在 C++ 中所做的事情:
void perform_long_running_task(bool* finished);
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func);
int seconds_to_wait {5};
int seconds_task_takes{6};
int main() {
start_task_and_throw_on_timeout(seconds_to_wait, &perform_long_running_task);
// do other stuff
return 0;
}
void perform_long_running_task(bool* finished){
// Do something that may possible timeout..
std::this_thread::sleep_for(std::chrono::seconds(seconds_task_takes));
// Finished..
*finished = true;
}
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func){
bool finished {false};
std::thread task(func, &finished);
while (secs > 0){
std::this_thread::sleep_for(std::chrono::seconds(1));
secs--;
if (finished){
task.join();
return;
}
}
throw std::exception();
}
这里,当'seconds_task_takes'大于'seconds_to_wait'时,主线程抛出异常。如果任务及时完成,一切都会顺利进行。
但是,我需要用动态脚本语言编写我的软件,这种语言可以 运行 在任何地方并且不需要编译。我会非常高兴任何关于如何编写类似 Ruby.
中的代码的建议
提前致谢:)
编辑:在示例中,我向 start_task_and_throw_timeout 添加了一个 std::function 参数,因此它可重复用于所有类似的功能
我认为模块 timeout
拥有您需要做的一切。它允许您 运行 块一段时间,如果它不够快则引发异常。
这是一个代码示例:
require "timeout"
def run(name)
puts "Running the job #{name}"
sleep(10)
end
begin
Timeout::timeout(5) { run("hard") }
rescue Timeout::Error
puts "Failed!"
end
您可以在这里玩:https://repl.it/repls/CraftyUnluckyCore. The documentation for the module lives here: https://ruby-doc.org/stdlib-2.5.1/libdoc/timeout/rdoc/Timeout.html。请注意,您不仅可以自定义超时时间,还可以自定义错误 class 和消息,因此不同的作业可能会有不同类型的错误。
我目前正在编写一个 Ruby 脚本,该脚本应该在相当长的主机列表上执行不同的任务。我正在使用 net-ssh gem 与这些主机建立连接。问题是,似乎存在某些情况下 net-ssh 超时而不会抛出异常。据了解,该脚本只能完成一次 运行。大多数时候,脚本只是在某个时刻挂起而不会抛出异常或执行任何操作。
我考虑过 运行在不同的线程中设置所有可能超时的任务,向它们传递一个指向某个变量的指针,当任务成功完成时它们可以更改,然后在给定的时间内检查该变量.如果到那时任务还没有完成,在主线程中抛出异常,我可以在某个地方捕获。
这是我第一次在Ruby写东西。为了清楚地展示我想要完成的事情,这就是我在 C++ 中所做的事情:
void perform_long_running_task(bool* finished);
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func);
int seconds_to_wait {5};
int seconds_task_takes{6};
int main() {
start_task_and_throw_on_timeout(seconds_to_wait, &perform_long_running_task);
// do other stuff
return 0;
}
void perform_long_running_task(bool* finished){
// Do something that may possible timeout..
std::this_thread::sleep_for(std::chrono::seconds(seconds_task_takes));
// Finished..
*finished = true;
}
void start_task_and_throw_on_timeout(int secs, std::function<void(bool*)> func){
bool finished {false};
std::thread task(func, &finished);
while (secs > 0){
std::this_thread::sleep_for(std::chrono::seconds(1));
secs--;
if (finished){
task.join();
return;
}
}
throw std::exception();
}
这里,当'seconds_task_takes'大于'seconds_to_wait'时,主线程抛出异常。如果任务及时完成,一切都会顺利进行。
但是,我需要用动态脚本语言编写我的软件,这种语言可以 运行 在任何地方并且不需要编译。我会非常高兴任何关于如何编写类似 Ruby.
中的代码的建议提前致谢:)
编辑:在示例中,我向 start_task_and_throw_timeout 添加了一个 std::function 参数,因此它可重复用于所有类似的功能
我认为模块 timeout
拥有您需要做的一切。它允许您 运行 块一段时间,如果它不够快则引发异常。
这是一个代码示例:
require "timeout"
def run(name)
puts "Running the job #{name}"
sleep(10)
end
begin
Timeout::timeout(5) { run("hard") }
rescue Timeout::Error
puts "Failed!"
end
您可以在这里玩:https://repl.it/repls/CraftyUnluckyCore. The documentation for the module lives here: https://ruby-doc.org/stdlib-2.5.1/libdoc/timeout/rdoc/Timeout.html。请注意,您不仅可以自定义超时时间,还可以自定义错误 class 和消息,因此不同的作业可能会有不同类型的错误。