异步方法调用的排序

本文关键字:排序 调用 异步方法 | 更新日期: 2023-09-27 17:55:17

我正在开发一个类库,该库根据 Web 配置文件中定义的策略在几种类型的数据源(文件、xml、数据库)中记录 Web 应用程序的审核详细信息。

我的审核日志方法具有类似于以下内容的签名:公共静态空 LogInfo(用户用户、模块模块、列表 lst);

Web 应用程序使用此方法记录重要的详细信息,如警告、错误甚至异常详细信息。

由于在单个工作流中,对这些方法的调用超过 700+ 次,我想使它们异步。我使用了ThreadPool类中名为QueueUserWorkItem 的简单方法

ThreadPool.QueueUserWorkItem(o => LogInfo(User user, Module module, List<Object> lst) );

但这并不能确保工作项排队的顺序。即使我所有的信息都被记录下来,但整个订单都被搞砸了。在我的文本文件中,我的日志没有按照调用它们的顺序排列。

有没有办法控制使用 QueueUserWorkItem 调用的线程的顺序?

异步方法调用的排序

我认为您在使用QueueUserWorkItem时无法指定排序。

要并行运行日志记录(在某些后台线程上),可以使用ConcurrentQueue<T> .这是一个可以从多个线程访问的线程安全集合。可以创建一个工作项(或线程),用于从集合中读取元素并将其写入文件。主应用程序会将项添加到集合中。从单个线程向集合添加项的事实应保证以正确的顺序读取它们。

为简单起见,您可以在队列中存储Action值:

ConcurrentQueue<Action> logOperations = new ConcurrentQueue<Action>();
// To add logging operation from main thread:
logOperations.Add(() => LogInfo(user, module, lst));

后台任务可以从队列中获取Action并运行它们:

// Start this when you create the `logOperations` collection
ThreadPool.QueueUserWorkItem(o => {
    Action op;
    // Repeatedly take log operations & run them
    while (logOperations.TryDequeue(out op)) op();
});

如果需要停止后台处理器(将数据写入日志),可以创建CancellationTokenSource并在取消令牌(由主线程)时结束while循环。使用IsCancellationRequested属性检查此 cha(请参阅 MSDN)

解决此问题的一种方法是将数据放入队列中,然后让单个任务从该队列中选取并按顺序写入它们。如果您使用的是 .net 4.0,则可以使用 ConcurrentQueue,它是线程安全的,否则具有正确锁的简单队列也可以使用。

然后,使用队列的线程可以定期检查队列中的任何元素,并且可以记录每个元素。这样,冗长的操作(日志记录)可以在其自己的线程中,而在主线程中,您只需添加即可。