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