c# 使用 System.Timers 时取消任务
c# Task cancellation when using System.Timers
我不确定取消正在 运行 系统计时器的任务的最佳方式。
在下面的代码中,计时器每 60 分钟就会计时一次,然后 运行 另一种方法 (CheckFileOverflow) 用于检查系统日志 txt 的文件大小。文件
理想情况下,可以通过单击按钮或调用取消的其他方法来取消计时器。只要软件处于 运行ning 状态,定时器就可以有效地 运行,但是当用户最终关闭软件时,我希望能够以负责任的方式取消任务即没有 运行 在后台使用持续线程池资源的风险。
我花了很多时间阅读取消令牌,但仍然不明白:(
public void SystemEventLoggerTimer()
{
SysEvntLogFileChckTimerRun = true;
Task.Run(() =>
{
System.Timers.Timer timer = new System.Timers.Timer
{ Interval = 1000 * 60 * 60 };
timer.Elapsed += new ElapsedEventHandler(CheckFileOverflow);
timer.Start();
});
}
你可以把你的方法改成这样
public void SystemEventLoggerTimer(CancellationToken cancelToken)
{
SysEvntLogFileChckTimerRun = true;
Task.Run(async () =>
{
// Keep this task alive until it is cancelled
while (!cancelToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromMinutes(60));
CheckFileOverflow();
}
});
}
然后你像这样调用SystemEventLoggerTimer
var cancelSource = new CancellationTokenSource();
SystemEventLoggerTimer(cancelSource.Token);
你可以在程序被释放时或者在你的主函数结束时取消这个令牌
为什么不在调用上下文中(或在您的 class/application 中全局)设置一个计时器 - 无论如何您都必须使用 CancellationTokenSource
来实现!这看起来不像 Task
.
的正确用例
试试这个:
public void SystemEventLoggerTimer(System.Timers.Timer timer)
{
SysEvntLogFileChckTimerRun = true;
timer.Elapsed += new ElapsedEventHandler(CheckFileOverflow);
timer.Start();
}
调用代码:
var timer = new System.Timers.Timer() { Interval = 1000 * 60 * 60 };
SystemEventLoggerTimer(timer);
取消代码(在取消按钮的事件处理程序等中):
timer.Stop();
我建议您使用 Microsoft 的 Reactive Framework(又名 Rx)- 只是 NuGet System.Reactive
。
然后你这样做:
IDisposable subscription =
Observable
.Interval(TimeSpan.FromHours(1.0))
.Subscribe(_ => CheckFileOverflow());
如果您想取消订阅,只需调用subscription.Dispose()
。
Rx 是抽象定时器、事件、任务、异步操作等的理想选择。
我在下面发布了一个似乎对我有用的令人满意的解决方案。希望我以正确的方式响应线程......(Whosebug 的新手)
我设置了一个用于测试的快速 windows 表单,我创建了 2 个按钮和 1 个文本框。
按钮用于启动和停止计时器(使用取消令牌)
文本框用于监视计时器,该计时器每 2 秒更新一次 "Timer Running" 消息。希望这可以帮助其他人看到类似的情况...
enter image description here
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private CancellationTokenSource cancelSource;
// Button is used to START the timer.
private void TimerStartButton_Click(object sender, EventArgs e)
{
cancelSource = new CancellationTokenSource();
// Run the below method that will initiate timer to start running from
// the button click.
SystemEventLoggerTimer(cancelSource.Token);
}
private void SystemEventLoggerTimer(CancellationToken cancelToken)
{
Task.Run(async () =>
{
// Keep this task alive until it is cancelled
while (!cancelToken.IsCancellationRequested)
{
// Encapsulating the function Task.Delay with 'cancelToken'
// allows us to stop the Task.Delay during mid cycle.
// For testing purposes, have reduced the time interval to 2 secs.
await Task.Delay(TimeSpan.FromSeconds(2), cancelToken);
// Run the below method every 2 seconds.
CheckFileOverflow();
}
});
}
// When the below method runs every 2 secs, the UpdateUI will allow
// us to modify the textbox form controls from another thread.
private void CheckFileOverflow()
{
UpdateTextbox("Timer Running");
}
// UpdateUI will allow us to modify the textbox form controls from another thread.
private void UpdateTextbox(string s)
{
Func<int> del = delegate ()
{
textBox1.AppendText(s + Environment.NewLine);
return 0;
};
Invoke(del);
}
// Button that is used to STOP the timer running.
private void TimerStopButton_Click(object sender, EventArgs e)
{
// Initiate the cancelleation request to method "SystemEventLoggerTimer"
cancelSource.Cancel();
}
}
我不确定取消正在 运行 系统计时器的任务的最佳方式。 在下面的代码中,计时器每 60 分钟就会计时一次,然后 运行 另一种方法 (CheckFileOverflow) 用于检查系统日志 txt 的文件大小。文件
理想情况下,可以通过单击按钮或调用取消的其他方法来取消计时器。只要软件处于 运行ning 状态,定时器就可以有效地 运行,但是当用户最终关闭软件时,我希望能够以负责任的方式取消任务即没有 运行 在后台使用持续线程池资源的风险。
我花了很多时间阅读取消令牌,但仍然不明白:(
public void SystemEventLoggerTimer()
{
SysEvntLogFileChckTimerRun = true;
Task.Run(() =>
{
System.Timers.Timer timer = new System.Timers.Timer
{ Interval = 1000 * 60 * 60 };
timer.Elapsed += new ElapsedEventHandler(CheckFileOverflow);
timer.Start();
});
}
你可以把你的方法改成这样
public void SystemEventLoggerTimer(CancellationToken cancelToken)
{
SysEvntLogFileChckTimerRun = true;
Task.Run(async () =>
{
// Keep this task alive until it is cancelled
while (!cancelToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromMinutes(60));
CheckFileOverflow();
}
});
}
然后你像这样调用SystemEventLoggerTimer
var cancelSource = new CancellationTokenSource();
SystemEventLoggerTimer(cancelSource.Token);
你可以在程序被释放时或者在你的主函数结束时取消这个令牌
为什么不在调用上下文中(或在您的 class/application 中全局)设置一个计时器 - 无论如何您都必须使用 CancellationTokenSource
来实现!这看起来不像 Task
.
试试这个:
public void SystemEventLoggerTimer(System.Timers.Timer timer)
{
SysEvntLogFileChckTimerRun = true;
timer.Elapsed += new ElapsedEventHandler(CheckFileOverflow);
timer.Start();
}
调用代码:
var timer = new System.Timers.Timer() { Interval = 1000 * 60 * 60 };
SystemEventLoggerTimer(timer);
取消代码(在取消按钮的事件处理程序等中):
timer.Stop();
我建议您使用 Microsoft 的 Reactive Framework(又名 Rx)- 只是 NuGet System.Reactive
。
然后你这样做:
IDisposable subscription =
Observable
.Interval(TimeSpan.FromHours(1.0))
.Subscribe(_ => CheckFileOverflow());
如果您想取消订阅,只需调用subscription.Dispose()
。
Rx 是抽象定时器、事件、任务、异步操作等的理想选择。
我在下面发布了一个似乎对我有用的令人满意的解决方案。希望我以正确的方式响应线程......(Whosebug 的新手) 我设置了一个用于测试的快速 windows 表单,我创建了 2 个按钮和 1 个文本框。 按钮用于启动和停止计时器(使用取消令牌) 文本框用于监视计时器,该计时器每 2 秒更新一次 "Timer Running" 消息。希望这可以帮助其他人看到类似的情况...
enter image description here
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private CancellationTokenSource cancelSource;
// Button is used to START the timer.
private void TimerStartButton_Click(object sender, EventArgs e)
{
cancelSource = new CancellationTokenSource();
// Run the below method that will initiate timer to start running from
// the button click.
SystemEventLoggerTimer(cancelSource.Token);
}
private void SystemEventLoggerTimer(CancellationToken cancelToken)
{
Task.Run(async () =>
{
// Keep this task alive until it is cancelled
while (!cancelToken.IsCancellationRequested)
{
// Encapsulating the function Task.Delay with 'cancelToken'
// allows us to stop the Task.Delay during mid cycle.
// For testing purposes, have reduced the time interval to 2 secs.
await Task.Delay(TimeSpan.FromSeconds(2), cancelToken);
// Run the below method every 2 seconds.
CheckFileOverflow();
}
});
}
// When the below method runs every 2 secs, the UpdateUI will allow
// us to modify the textbox form controls from another thread.
private void CheckFileOverflow()
{
UpdateTextbox("Timer Running");
}
// UpdateUI will allow us to modify the textbox form controls from another thread.
private void UpdateTextbox(string s)
{
Func<int> del = delegate ()
{
textBox1.AppendText(s + Environment.NewLine);
return 0;
};
Invoke(del);
}
// Button that is used to STOP the timer running.
private void TimerStopButton_Click(object sender, EventArgs e)
{
// Initiate the cancelleation request to method "SystemEventLoggerTimer"
cancelSource.Cancel();
}
}