C# 如何使用不同的时间间隔安排异步执行?

C# 如何使用不同的时间间隔安排异步执行?,c#,async-await,C#,Async Await,我有两套作业需要单独执行,不能并行运行。作业涉及web通信,因此使用异步 目前,我已经设置了System.Windows.Forms.Timers,以使用Task.Run()执行批处理。为了避免可能的同时执行,首先我认为我可以简单地在计时器的滴答声中使用lock(){}(我用滴答声的倒计时来更新UI)。然后意识到我需要.Wait()才能完成任务,否则它只会退出关键部分 然后我意识到所有这些都是在UI线程上运行的,所以这就像Elmer Fudd的那些场景,他将步枪指向一个洞,而另一个洞的末端指向他

我有两套作业需要单独执行,不能并行运行。作业涉及web通信,因此使用异步

目前,我已经设置了
System.Windows.Forms.Timer
s,以使用
Task.Run()
执行批处理。为了避免可能的同时执行,首先我认为我可以简单地在计时器的
滴答声中使用
lock(){}
(我用滴答声的倒计时来更新UI)。然后意识到我需要
.Wait()
才能完成任务,否则它只会退出关键部分

然后我意识到所有这些都是在UI线程上运行的,所以这就像Elmer Fudd的那些场景,他将步枪指向一个洞,而另一个洞的末端指向他

是否有一种简单的钉锤方法可以在保持相互排斥的执行的同时不阻塞UI线程

以下是其中一个计时器的示例:

_timer = new Timer { Interval = 1000 };
_timer.Tick += (sender, args) =>
{
    var timeSpan = _nextRun - DateTime.Now;
    if (timeSpan.Seconds >= 0)
    {
        UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
    }
    else
    {
        lock (_runLock)
        {
            Task.Run(() => RunJobs(_batch1Jobs)).Wait();
        }
    }
};
为了更清楚地说明这一点,有第二个计时器,比如说它叫
\u timer2
,它同样会更新一个不同的倒计时,并在达到0时运行
\u batch2Jobs

您应该使用任务:

Task T1 = Task.Factory.StartNew(() => {/*do work */});
Task T2 = T1.ContinueWith((antecedent) => {/*do work 2*/});

首先,您需要摆脱
lock
并切换到

那么你可以用这样的东西

_timer.Tick += async (sender, args) =>
{
    var timeSpan = _nextRun - DateTime.Now;
    if (timeSpan.Seconds >= 0)
    {
        UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
    }
    else
    {
        _timer.Enabled = false;
        try
        {
            await Task.Run(async () =>
            {
                await _runLock.WaitAsync();
                try { RunJobs(_batch1Jobs); }
                finally { _runLock.Release(); }
            });
        }
        finally { _timer.Enabled = true; }
    }
};

请注意,永远不要使用
锁定
任务。在UI线程上等待长时间运行的任务。UI代码应该只使用
async/await
结构。

但我不知道是否有延续。有一个不同的计时器对象在为单独的批处理运行。我不清楚您想要什么。从您的代码中,我看到只要_nextRun-DateTime,您就会更新UI。现在>0,当您达到0时,您会执行一些作业,所以为什么不想在单独的任务中运行这些作业呢?您的问题很模糊。你到底想在这里实现什么。也许描述一下实际的问题。什么是批处理作业
?它做什么?这是正确的方法,但是因为滴答声可以同时传递,所以我将把关键部分扩展到整个方法。就目前情况而言,这很有活力。此外,禁用计时器是一种快速行为,可能不会立即生效。可能不应该使用计时器。一个Task.Delay循环会更好。信号量(slim)比锁有什么优势?您可以等待获得它吗?@usr OP使用的是
System.Windows.Forms.Timer
,IMO没有这个功能。当然还有其他选择。啊,一个窗体计时器。对,那里没有比赛。但wait从UI线程中退出,这使得多个tick处理程序从此点开始并发运行。所以它仍然很活泼。您可能会得到以下启用顺序:false、false、true、true。
_timer.Tick += async (sender, args) =>
{
    var timeSpan = _nextRun - DateTime.Now;
    if (timeSpan.Seconds >= 0)
    {
        UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
    }
    else
    {
        _timer.Enabled = false;
        try
        {
            await Task.Run(async () =>
            {
                await _runLock.WaitAsync();
                try { RunJobs(_batch1Jobs); }
                finally { _runLock.Release(); }
            });
        }
        finally { _timer.Enabled = true; }
    }
};