C# 完成后,将再次调用Simple方法

C# 完成后,将再次调用Simple方法,c#,performance,C#,Performance,背景: 我有一个方法,可以进行一些处理,我希望被反复调用。该方法可能需要50-200毫秒才能完成 目前,我有一个System.Timers.Timer,它每250毫秒调用一次该方法。我觉得我可以通过让该方法在完成后自行“触发”来提高效率 注: 性能是关键 其中两个方法不应同时调用,也不应重叠 我希望避免简单地使用调用该方法的while循环。它应该使用事件异步调用自己 问题: 方法“trigger”一旦完成,我怎么能让它自己呢?你可以在一个单独的执行线程中执行循环,只要你对锁、条件变量、等待句

背景:

我有一个方法,可以进行一些处理,我希望被反复调用。该方法可能需要50-200毫秒才能完成

目前,我有一个
System.Timers.Timer
,它每250毫秒调用一次该方法。我觉得我可以通过让该方法在完成后自行“触发”来提高效率

注:

  • 性能是关键
  • 其中两个方法不应同时调用,也不应重叠
我希望避免简单地使用调用该方法的
while
循环。它应该使用事件异步调用自己

问题:


方法“trigger”一旦完成,我怎么能让它自己呢?

你可以在一个单独的执行线程中执行
循环,只要你对锁、条件变量、等待句柄等采取必要的多线程预防措施

  • C#s可能适合这份工作。但正如里德所说,一定要使用创建选项。里德发布了一个这种方法的例子
  • 或者直接使用对象。SLaks发布了这种方法的一个示例

如果您使用的是WinForms应用程序,您可能需要考虑使用。

创建一个新线程,在
while
循环中连续调用您的方法

void DoBackgroundPolling() {
    while(true) {
        try {
            YourMethod();
        } catch(Exception ex) {
            log error
        }
    }
}

new Thread(DoBackgroundPolling).Start()

如果希望能够控制轮询,可以在该方法中检查布尔字段。

这可以使用TPL相当干净地处理。在主线程中,您可以通过以下方式在后台启动此任务:

public delegate void MyDelegate(void);

void MyMethod()
{
  do stuff;
  this.Dispatcher.BeginInvoke(new MyDelegate(MyMethod), null);
}
CancellationTokenSource cancel = new CancellationTokenSource();

Task.Factory
      .StartNew(() => PollHardware(cancel.Token), TaskCreationOptions.LongRunning)
      .ContinueWith(t =>
        {
            if (t.IsFaulted)
            {
                var aggException = t.Exception; // Keep task from pulling down AppDomain
                // Log/handle/etc
                LogException(aggException.InnerException);
            }
        });
然后,您只需要一个方法来处理循环:

void PollHardware(CancellationToken token)
{
     while(true)
     {           
         token.ThrowIfCancellationRequested();
         YourMethod();
     }
} 


当您希望停止轮询时,可以调用:
cancel.cancel()

为什么要避免使用无限循环?如果{recursive\u call()},while循环有什么问题?这听起来像是一个简单的最佳解决方案。您将毫无理由地增加复杂性。我的程序执行其他处理,而此方法轮询硬件。如果使用while循环,这会在不同的线程中完成吗?如果是这样,你能举个简单的例子吗。谢谢。我似乎有种很傻的感觉。我只想在一些基准测试中指出它的优点:与UI计时器不同,它不需要使用windows消息队列。“最有效的”是
而(shouldContinue){DoTheMethod()}
在线程中——但这真的是我们想要的吗?(如果是,为什么要先使用计时器呢?)您不应该永远使用线程池线程;线程池是用来完成短任务的。是的,我只是在方法中加入while循环。在单独的线程上触发一次。如果需要停止,请使用CancellationToken。@SLaks:TPL可以这样做-但是任务应该应用
LongRunning
提示。@Reed和Ryan我喜欢运行任务的想法。你能给我一些简单的代码让我开始吗?谢谢。请注意,任务也将在单独的线程上运行。它看起来就像我的代码,但是在
任务
中,而不是在
线程
中。它仍然需要线程安全。他想在后台运行。它在哪里说的?他目前在前台线程上运行它,并用计时器调用它。他没有提到多线程或在后台运行,只是希望在前一次调用完成后立即运行。请参见他对问题的评论。实际上,所有其他处理都在前台完成,但我认为在后台运行此轮询方法可能更好。从我所知,他只是说他不想永远用无限的时间来锁定主线,这是很合理的。将他的方法与调度器一起排队将允许主线程执行其他工作,从而避免使用循环带来的问题。他甚至可以根据自己的喜好调整优先级,一直到ApplicationIdle。编辑:别误会我的意思,我认为运行后台while循环是最好的解决方案,前提是不存在任何需要解决的大型同步问题,但我认为这是一个可行的解决方案,因为他不想要循环。我将存储我轮询的数据中的许多变量。因为这是在一个单独的线程中运行的,所以我应该采取什么预防措施吗?@Ryan:当然。关于线程安全开发的完整讨论超出了本文的讨论范围。感谢您的帮助,我已经请@Ryan S链接您的实现。感谢您的代码。我将不得不调查我的线程安全性。@Ryan R:这会引入任何新的线程安全问题,因为您现有的代码正在使用后台线程(计时器的勾号事件在线程池线程上)。也就是说,与主线程共享的任何数据都需要同步。感谢您的帮助,我已经要求@Ryan S链接您的TPL实现。