每个特定时间执行方法(ms)

时间:2015-07-07 14:31:45

标签: c# multithreading

我希望在以下条件下执行每个特定时间(例如25 ms)的输入方法:

  1. 每25毫秒运行一次方法。
  2. 如果方法延迟大于25毫秒,则停止执行并从头开始为新输入。
  3. 提示:我使用了以下代码但是如果方法延迟>它没有停止执行。 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()
    }    
    

    由于

3 个答案:

答案 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.WriteLineDebug.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.