Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 只需要第一个任务,忽略其他任务_C#_Asynchronous_Async Await - Fatal编程技术网

C# 只需要第一个任务,忽略其他任务

C# 只需要第一个任务,忽略其他任务,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我想在指定的时间间隔调用任务。并避免调用新任务,除非最后一个任务已经完成 private async void OnTimerTick(object sender, object e) { if (_criticalSection.IsEntered()) return; // only allow 1 at any given time, ignore the rest using (var section = await _criticalSectio

我想在指定的时间间隔调用任务。并避免调用新任务,除非最后一个任务已经完成

private async void OnTimerTick(object sender, object e)
{            
    if (_criticalSection.IsEntered()) return; // only allow 1 at any given time, ignore the rest
    using (var section = await _criticalSection.EnterAsync())
    {
        await update();
    }
}
我如何做到这一点?对更好的模式有什么建议吗?

关键部分(如窗口的互斥)是为了相互排斥:只允许单个线程进入代码路径

但这并不是你想要做的:你需要一些东西来告诉你是否发生了什么事情

更好的方法是手动重置事件:在任务开始时设置它(也称为信号),然后在任务结束时重置。然后,您可以通过等待正常窗口事件的超时为零来检查它是否发出了信号,或者对于其他类型的事件,您可以使用适用的成员来检查它是否发出了信号

由于这似乎是一个单一的过程,一个良好的起点是。使用类似于:

// One off initialisation somewhere at class scope
private static ManualResetEventSlim taskRunning = new ManualResetEventSlim();
private static object taskLock = new Object();

// code called from the timer, do in a lock to avoid race conditions with two
// or more threads call this.
lock (taskLock) {
  if (!taskRunning.IsSet) {
    StartTheTask(); // assuming this does not return until task is running.
  }
}

// At the outermost scope of the code in the task:
try {
  Debug.Assert(!taskRunning.IsSet); // Paranoia is good when doing threading
  taskRunning.Set();

  // Task impementation

} finally {
  Debug.Assert(taskRunning.IsSet); // Paranoia is good when doing threading
  taskRunning.Reset();
}

另一种方法是始终启动任务,但让它检查事件,如果设置了,则立即退出。这仍然需要
lock
来避免
IsSet
Set()
调用之间的线程冲突。第二种方法将检查代码放在一起,代价是短暂地运行另一个任务(除非这是常见的,否则我可能会对代码位置采用这种方法)。

您的代码不是线程安全的,它是一场竞赛。@SriramSakthivel:您的意思是,在using块的延续版本和IsEntered版本之间存在竞赛?但是如果SynchronizationContext是相同的,那怎么会有竞争呢?反应又好又快,谢谢。但是Win32的TryIntercriticalSection()和SemaphoreSlim的timeout参数背后的原因是什么?它们在逻辑上不适用吗?@user3127135正如答案中提到的关键部分(如muxtex)是错误类型的同步对象。可以使用信号量,但您不需要它提供的计数:它会更复杂。使用ManualResetEventSlim和线程安全布尔标志之间有什么区别吗?@Ricard。啊,我明白了。它可以提供手段,但它不应该被用来做什么。可读性、复杂性和意图。好的,很好:)