【问题标题】:How do run code on the same thread with System.Threading.Timer c#如何使用 System.Threading.Timer c# 在同一线程上运行代码
【发布时间】:2020-06-23 20:49:05
【问题描述】:

我有一个应用程序,它应该每隔几秒钟运行一个方法,但要等到上一次运行完成。我已经通过在metod运行之前禁用计时器来解决这个问题,如下面的代码所示。我怀疑无论如何都会不时调用另一个线程。我想在同一个线程上运行所有内容。关于如何使用 system.threading.timer 的任何想法?

提前致谢。

  timer = new System.Threading.Timer((e) =>
  {

    Console.WriteLine("*** Running Code *** ");
    Console.WriteLine(DateTime.Now);

    timer.Change(Timeout.Infinite, Timeout.Infinite);

    MyMethod();

    timer.Change(periodTimeSpanGet,periodTimeSpanGet);

    Console.WriteLine("*** Code Finished Code *** ");
    Console.WriteLine(DateTime.Now);

}
, null, startTimeSpan, periodTimeSpanGet);

`

【问题讨论】:

  • 为什么“在同一个线程上”?这会带来什么好处?定时器回调发生在线程池中,所以不一定在同一个线程上。
  • 使用SynchronizationContext Post 或 Send(假设你试图编组的线程不是线程池并且支持这个)
  • 看来您的问题是不需要的并发性(重叠执行),而不是每次执行都可能发生在不同的线程中。第二个问题的解决方案也是第一个问题的解决方案,但可能不是最佳解决方案。
  • 谢谢。如何解决不需要的并发?
  • 您可以通过等待Task.DelaySemaphoreSlimWaitAsync 方法以初始计数= 1 实例化,轻松解决不必要的并发问题。您的问题已经有了很好的答案你想要的,但不是你在标题中要求的!

标签: c# multithreading timer


【解决方案1】:

为什么不只运行一个异步循环?

 while(someCondition)
 {
      DoTheWork();
      await Task.Delay(someAmountOfTime);
 }

如果时间很重要,您可以运行StopWatch 来测量时间的流逝并进行一些计算以找出someAmountOfTime 应该是什么。否则,只需使用一个常量值。

【讨论】:

  • 此解决方案不保证执行之间的恒定间隔。为了使其保持不变(假设每个作业的持续时间少于延迟时间),您应该在执行作业之前创建Task.Delay 任务,然后在之后创建await 任务。
  • @TheodorZoulias 是的,但是 OPs 现有的解决方案使用了固定的间隔 between 作业,所以这大致相同。不过,我喜欢在工作之前设置延迟的想法。不错。
  • @你是对的。您的解决方案与 OP 的当前设置相匹配。我相信他们会更喜欢恒定的间隔。 :-)
【解决方案2】:

您需要使用共享信号量将您的方法的并发执行次数限制为一次 1。在启动计时器之前将信号量实例化一次,并在每次执行计时器时重用它。

当方法启动时,您需要等待信号量可用。在方法结束时,您需要释放信号量。这样可以确保在等待和释放之间一次只执行一次。

使用信号量比锁定更好,因为它允许您提供超时,即放弃前等待的最长时间。

https://docs.microsoft.com/dotnet/standard/threading/semaphore-and-semaphoreslim

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2020-01-01
    • 2018-11-05
    • 1970-01-01
    • 2022-11-11
    • 2020-08-15
    相关资源
    最近更新 更多