当前位置: 首页 > 知识库问答 >
问题:

在 C 语言中构建基于时间的异步服务的好方法#

乐山
2023-03-14

我需要构建一个理论上将永远运行的服务。

运行时,它需要每隔几秒钟检查一次本地缓存,如果它在该缓存中找到新项目,它应该为每个新项目创建并执行一个新任务

我的问题是,实现这种服务的好方法是什么?我主要关心的是我应该如何执行异步任务的基于时间的启动。

我想出了两种方法来做到这一点

>

  • 使用 System.Timers.Timer 推送事件,然后在触发事件时运行代码

    创建一个将使用 Task.Delay 调用自身的方法

    以下是我所说的这两种方法的一些示例:

    小时

    public void Run()
    {
        System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(2).TotalMilliseconds);
        CancellationTokenSource ts = new CancellationTokenSource();
    
        timer.Elapsed += async (sender, argz) => await CodeExecutor(ts.Token);
        timer.Start();
    }
    
    public async Task CodeExecutor(CancellationToken token)
    {
        //Some logic
    }
    

    任务延迟

    private async Task RepeatableMethod(CancellationToken cancellationToken)
    {
        try
        {
            //some logic
        }
        catch (Exception e)
        {
        }
        finally
        {
            await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken)
                .ContinueWith(_ => RepeatableMethod(cancellationToken),cancellationToken);
        }
    }
    

    我不确定哪种方法更适合我的方案,如果没有不同的方法,那将比这两种方法更好。我主要关心的是,我希望每 2 秒执行一次的逻辑是异步的,并且可能是并行的。

    在以下情况下,什么被认为是更好的方法,是否有另一种(好的)方法可以处理我的案件?

  • 共有3个答案

    翟冯浩
    2023-03-14

    使用事件可以解决您的问题吗?只要将某些内容添加到缓存中,您就可以发出一个事件,并在事件侦听器中执行适当的操作。

    宋瀚海
    2023-03-14

    下面形式的粗略异步计时器当然是可能的:

    async Task Timer(Timespan interval, Func<Task> someCallback, CancellationToken token)
    {
         while (!token.IsCancellationRequested)
         {
            await Task.Delay(interval, token);
            await someAction(); // Or someAction?.Invoke();
         }
    }
    

    但是,有一些事情需要注意:

    • 在实践中,使用 Task.Delay 并不像 System.Threading.Timer 那样准确,因为需要计划延续的执行 - 在高负载情况下,我发现精度通常低于 15 毫秒。
    • 需要考虑
    • 回调(someAction)所花费的时间。如果这不是微不足道的,那么您可能需要在回调周围添加一个秒表,然后从下一个任务中减去回调所花费的时间。如果您需要相当准确的回调频率,请延迟。
    • 您需要担心重入。如果回调时间超过延迟时间,则计时器将受到限制。在这种情况下,您可能需要在回调上删除 await(如果它是异步的),在最坏的情况下,如果回调中存在显着的同步延迟,那么您可能还需要在其自己的线程上启动回调(例如 Task.Run(() =

    对我来说,我通常会使用基于System.Threading.Timer的解决方案 - 它更准确并且是可重入的,并且无论如何都可以同时创建大量计时器,因此基于Task.Delay的计时器似乎没有什么用处。

    糜博远
    2023-03-14

    据我所知,它看起来类似于生产者/消费者模式

    在这种情况下,您可以使用类似 BlockingCollection 的东西,但它不是异步的,这意味着在这种情况下需要一个等待项目的专用线程。Stephen Cleary在他的AsyncEx库中有一个异步实现,可以提供类似的功能。有关它的更多信息可以在他的博客中找到。

    或者TPL数据流可能合适,请查看此示例。

     类似资料:
    • 本文向大家介绍C语言实现在windows服务中新建进程的方法,包括了C语言实现在windows服务中新建进程的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C语言实现在windows服务中新建进程的方法。分享给大家供大家参考。具体如下: 运行环境:visual stdio 2008 文件名:testService.c 使用方法: 安装服务:sc create testService

    • braft 本身并不提供server功能, 你可以将braft集成到包括brpc在内的任意编程框架中,本文主要是阐述如何在分布式Server中使用braft来构建高可用系统。具体业务如何实现一个Server,本文不在展开。 Example server-side code of Counter 注册并且启动Server braft需要运行在具体的brpc server里面你可以让braft和你的业

    • 我开始学习C#TAP编码。我不明白为什么代码是同步运行的

    • 本文向大家介绍Objective-C语言创建基本方法,包括了Objective-C语言创建基本方法的使用技巧和注意事项,需要的朋友参考一下 示例 这是如何创建将“ Hello World”记录到控制台的基本方法: 的-开头表示该方法作为一个实例方法。 该(void)表示的返回类型。此方法不返回任何内容,因此您输入void。 “ hello”是方法的名称。 {}调用方法时,代码中的所有内容都会运行。

    • 本文向大家介绍c# 基于任务的异步编程模式(TAP),包括了c# 基于任务的异步编程模式(TAP)的使用技巧和注意事项,需要的朋友参考一下 异步编程是C#5.0的一个重要改进,提供两个关键字:async和await。使用异步编程,方法的调用是在后台运行(通常在线程或任务的帮助下),但不会阻塞调用线程。异步模式分为3种:异步模式、基于事件的异步模式和基于任务的异步模式(TAP)。TAP是利用关键字a

    • 本文向大家介绍C语言中时间戳转换成时间字符串的方法,包括了C语言中时间戳转换成时间字符串的方法的使用技巧和注意事项,需要的朋友参考一下 在PE格式里有个字段是文件的创建时间戳,我想把转成字符串,这样看的更直观。 以上所述是小编给大家介绍的C语言中时间戳转换成时间字符串的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对呐喊教程网站的支持!

    • 自然语言具有范围广泛的语法结构,用8.中所描述的简单的方法很难处理的如此广泛的语法结构。为了获得更大的灵活性,我们改变我们对待语法类别如S、NP和V的方式。我们将这些原子标签分解为类似字典的结构,其特征可以为一个范围的值。 本章的目的是要回答下列问题: 我们怎样用特征扩展上下文无关语法框架,以获得更细粒度的对语法类别和产生式的控制? 特征结构的主要形式化属性是什么,我们如何使用它们来计算? 我们现

    • 本文向大家介绍c# 基于任务的异步编程模式(TAP)的异常处理,包括了c# 基于任务的异步编程模式(TAP)的异常处理的使用技巧和注意事项,需要的朋友参考一下 在前面讲到了《基于任务的异步编程模式(TAP)》,但是如果调用异步方法,没有等待,那么调用异步方法的线程中使用传统的try/catch块是不能捕获到异步方法中的异常。因为在异步方法执行出现异常之前,已经执行完毕。 1、没有等待的调用异步方法