异步方法调用的顺序

发布于 2024-11-05 13:45:56 字数 577 浏览 1 评论 0原文

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

我的审核日志方法具有与此类似的签名: 公共静态无效LogInfo(用户用户,模块模块,列表lst);

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

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

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

但这并不能确保工作项的排队顺序到它。尽管我的所有信息都已记录,但整个订购都被搞乱了。在我的文本文件中,我的日志未按调用顺序排列。

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

I am working on a class library that logs audit details of a web application in several types of datasources(file, xml, database) based on policies defined in the web configuration file.

My Audit log method has a signature similar to this:
public static void LogInfo(User user, Module module, List lst);

Web application uses this method to log important pieces of details like warnings, error and even exception details.

Since in a single workflow, there are more than 700+ calls to these methods , I thought of making them asynchronous. I used simple method from ThreadPool class called QueueUserWorkItem

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

but this does not ensure the order in which work item was queued to it. Even though all my information was logged but entire ordering was messed up. In my text file my logs were not in the order in which they were called.

Is there a way I can control the ordering of the threads being called using QueueUserWorkItem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

未央 2024-11-12 13:45:56

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

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

为了简单起见,您可以将 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 属性 (参见 MSDN)

I don't think you can specify ordering when using QueueUserWorkItem.

To run the logging in parallel (on some background thread), you could use ConcurrentQueue<T>. This is a thread-safe collection that can be accessed from multiple threads. You could create one work item (or a thread) that reads elements from the collection and writes them to a file. Your main application would add items to the collection. The fact that you're adding items to the collection from a single thread should guarantee that they will be read in the right order.

To keep things simple, you can store Action values in the queue:

ConcurrentQueue<Action> logOperations = new ConcurrentQueue<Action>();

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

The background task can just take Actions from the queue and run them:

// 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();
});

If you need to stop the background processor (that writes data to the log), you can create a CancellationTokenSource and also end the while loop when the token is being cancelled (by the main thread). This cha be checked using IsCancellationRequested property (see MSDN)

把昨日还给我 2024-11-12 13:45:56

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

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

One way of solving this would be to put your data in a queue, and then having a single task picking from that queue and writing them in order. If you are using .net 4.0 You could use ConcurrentQueue, which is thread safe, otherwise a simple Queue with proper locks would work as well.

The thread consuming the queue could then periodically check for any element inside the queue, and for each one of them it could log. This way the lengthy operation (logging) could be in its own thread, whereas in the main thread you do simply adds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文