异步方法调用的排序
本文关键字:排序 调用 异步方法 | 更新日期: 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,它是线程安全的,否则具有正确锁的简单队列也可以使用。
然后,使用队列的线程可以定期检查队列中的任何元素,并且可以记录每个元素。这样,冗长的操作(日志记录)可以在其自己的线程中,而在主线程中,您只需添加即可。