【问题标题】:how to use async and await in timer如何在计时器中使用异步和等待
【发布时间】:2026-02-05 14:55:01
【问题描述】:

我的 Windows 应用程序的要求是:

  1. 使用 HttpWebRequest 在一个线程中每 3 秒获取一次 Web 请求/响应。(执行此 Web 请求/响应的线程总数约为 10 个。)

  2. 每个线程都使用一些全局变量。

我想使用 System.Timers.Timer 和异步等待。但我不知道这是实现高性能的最佳方式。然后如何测试它们。我是 C# 的新手。

【问题讨论】:

  • 使用Timer吗?您可以改用Task.Delay() 吗?如果是这样,我可以给你举个例子。
  • @user2724902,您不需要创建 10 个线程来并行执行 HttpWebRequest。使用WebRequest.GetResponseAsync

标签: c# multithreading asynchronous httpwebrequest async-await


【解决方案1】:

你可以写一个RepeatActionEvery()方法如下。

它的参数是:

  • action - 你想经常重复的动作。
  • interval - 调用 action() 之间的延迟间隔。
  • cancellationToken - 用于取消循环的令牌。

这是一个可编译的控制台应用程序,演示了如何调用它。对于 ASP 应用程序,您可以从适当的位置调用它。

请注意,您需要一种取消循环的方法,这就是我将CancellationToken 传递给RepeatActionEvery() 的原因。在这个示例中,我使用了一个取消源,它会在 8 秒后自动取消。您可能必须在适当的时候提供一个取消源,其中一些其他代码称为.Cancel()See here for more details.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    sealed class Program
    {
        void run()
        {
            CancellationTokenSource cancellation = new CancellationTokenSource(
              TimeSpan.FromSeconds(8));
            Console.WriteLine("Starting action loop.");
            RepeatActionEvery(() => Console.WriteLine("Action"), 
              TimeSpan.FromSeconds(1), cancellation.Token).Wait();
            Console.WriteLine("Finished action loop.");
        }

        public static async Task RepeatActionEvery(Action action, 
          TimeSpan interval, CancellationToken cancellationToken)
        {
            while (true)
            {
                action();
                Task task = Task.Delay(interval, cancellationToken);

                try
                {
                    await task;
                }
                catch (TaskCanceledException)
                {
                    return;
                }
            }
        }

        static void Main(string[] args)
        {
            new Program().run();
        }
    }
}

【讨论】:

  • 是否有任何理由倾向于捕获 TaskCanceledException 而不是检查 cancelToken.IsCancellationRequested 属性来代替 while 条件中的 true 语句?
  • @EhouarnPerret 如果将cancellationToken 传递给Task.Delay(),那么如果令牌被取消,它将抛出TaskCanceledException,因此您必须捕获异常。
  • 我很糟糕,我期待在没有检查 msdn 的情况下在 Task.Delay 中取消另一个行为,叹息。无论如何,谢谢它现在对我来说很有意义。
  • 我试图在flutter程序中实现这个(flutter使用Dart作为基础),这些功能似乎没有出现。有什么特别的原因可以让您想到为什么会这样,或者更好的是,任何合理的解决方案?