我希望在以下条件下执行每个特定时间(例如25 ms)的输入方法:
提示:我使用了以下代码但是如果方法延迟>它没有停止执行。 25毫秒
private Timer timer1;
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Interval = 1000/40;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
mymethod()
}
由于
答案 0 :(得分:2)
我没有机会运行它并检查其100%准确,但这应该让您了解如何使用Task
来解决问题:
public class Something
{
public Task _myMethodTask;
public CancellationTokenSource _cancelToken;
public Timer _myTimer;
public Random _rnd;
public void Start()
{
_rnd = new Random((int)DateTime.Now.Ticks);
_myTimer = new Timer(TimerElapsedHandler);
_myTimer.Change(25, 25);
}
public void TimerElapsedHandler(object state)
{
if (!_myMethodTask.IsCompleted)
{
//The current task is taking too long
_cancelToken.Cancel();
}
_cancelToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(25));
_myMethodTask = new Task(() => MyMethod(), _cancelToken.Token);
}
public void MyMethod()
{
Stopwatch sw = new Stopwatch();
sw.Start();
int delayTimeMs = _rnd.Next(5, 50);
while (sw.ElapsedMilliseconds < delayTimeMs)
{
try
{
_cancelToken.Token.ThrowIfCancellationRequested();
Thread.Sleep(1);
}
catch (TaskCanceledException)
{
return;
}
}
}
}
发生的事情是它使用一个每25毫秒运行一次的计时器(在这种情况下为System.Threading.Timer
)。它启动一项新任务,取消时间为25毫秒。任务是MyMethod()
,只是为了模拟一个长时间运行的过程,它会延迟一个随机时间。您可以添加一些Console.WriteLine
或Debug.WriteLine
来看它是否有效。
需要注意的重要一点是,您必须定期致电_cancelToken.Token.ThrowIfCancellationRequested();
,而不只是一次。如果请求取消,该方法将抛出异常,如果需要,您可以在退出之前清理。如果您不打电话,任务将不会取消。
答案 1 :(得分:0)
只需使用System.Timers.Timer,不要使用System.Threading.Timer
timer1 = new System.Timers.Timer(1000 / 25);
并修改Tick事件
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
mymethod()
timer1.Start();
}
但没有保证mymethod抛出异常等你也应该管理它们。
答案 2 :(得分:0)
我有使用反应式扩展的此解决方案。我不得不按订单增加时间跨度,因为睡眠不够精确。以下代码显示即使先前失败,actual
变量也在增加
您还必须在mymethod()
函数上调整一些。如果昂贵的方法是I / O繁重的功能,而不是将其分成缓冲区,并且每个缓冲区写入/读取您可以检查令牌是否仍未被取消。这样,可以调整阻挡部分的长度。
static Random rand = new Random();
static void Main(string[] args) {
var obs = Observable.Interval(TimeSpan.FromMilliseconds(250)).Do<long>(i =>
{
CancellationTokenSource source = new CancellationTokenSource(250);
ReadNext(source.Token, i);
}).Publish();
var disp = obs.Connect();
Console.ReadKey();
disp.Dispose();
Console.ReadKey();
}
static private void ReadNext(CancellationToken token, long actual) {
int i = rand.Next(4);
for(int j = 0; j < i; j++) {
Thread.Sleep(100);
if(token.IsCancellationRequested) {
Console.WriteLine(string.Format("method cancelled. cycles: {0}, should be 3. Now should be last (2): {1}", i, j));
return;
}
}
Console.WriteLine(string.Format("method done in {0} cycles. Preserved index: {1}.", i, actual));
}
示例打印输出:
method done in 2 cycles. Preserved index: 4.
method done in 0 cycles. Preserved index: 5.
method done in 0 cycles. Preserved index: 6.
method done in 2 cycles. Preserved index: 7.
method done in 1 cycles. Preserved index: 8.
method cancelled. cycles: 3, should be 3. Now should be last (2): 2
method done in 0 cycles. Preserved index: 10.
method cancelled. cycles: 3, should be 3. Now should be last (2): 2
method cancelled. cycles: 3, should be 3. Now should be last (2): 2
method cancelled. cycles: 3, should be 3. Now should be last (2): 2
method done in 1 cycles. Preserved index: 14.
method cancelled. cycles: 3, should be 3. Now should be last (2): 2
method done in 1 cycles. Preserved index: 16.
method done in 2 cycles. Preserved index: 17.
method cancelled. cycles: 3, should be 3. Now should be last (2): 2
method done in 2 cycles. Preserved index: 19.
method done in 1 cycles. Preserved index: 20.
method done in 2 cycles. Preserved index: 21.
method done in 2 cycles. Preserved index: 22.
method done in 1 cycles. Preserved index: 23.
method done in 1 cycles. Preserved index: 24.
method done in 1 cycles. Preserved index: 25.
method done in 2 cycles. Preserved index: 26.
method done in 1 cycles. Preserved index: 27.