【问题标题】:Are there any implications or pitfalls of accessing RabbitMQ IModel through a ThreadLocal?通过 ThreadLocal 访问 RabbitMQ IModel 是否有任何影响或陷阱?
【发布时间】:2025-12-01 08:50:01
【问题描述】:

我创建了一个类来促进通过队列进行简单的文本消息传输

public class TextQueueTransmitter
{
    private Func<IModel> channelProvider;
    private IBasicProperties props;
    private string queue;

    public TextQueueTransmitter(Func<IModel> channelProvider, string queue)
    {
        this.queue = queue;
        this.channelProvider = channelProvider;
        
         //will be called once in a thread
        this.channelProvider().QueueDeclare(queue: queue,
                             durable: false,
                             exclusive: false,
                             autoDelete: false,
                             arguments: null);
        props = this.channelProvider().CreateBasicProperties();
    }

    public void SendMessage(string message)
    {
        var body = Encoding.UTF8.GetBytes(message);
        props.DeliveryMode = 1;
        
        //will be called multiple times not necessarily in the same thread
        channelProvider().BasicPublish(exchange: "",
            routingKey: queue,
            basicProperties: null,
            body: body);
    }
}

初始化会像

IConnection connection = ...
ThreadLocal channelThreadLocal = new ThreadLocal<IModel>(connection.CreateModel);
TextQueueTransmitter transmitter = new TextQueueTransmitter(() => channelThreadLocal.Value, "queue name");

以前我是直接将 IModel 传递给发送器,但在阅读 here 说 IModel 不是线程安全的之后,我意识到如果我想让 TextQueueTransmitter 线程安全,我必须重新考虑它。

我的问题是仅将 IModel 包装在 ThreadLocal 中是否有任何影响?例如,如果在构造对象的线程之外的线程中调用 SendMessage(),则将在不同的线程上调用 QueueDeclareBasicPublish。会不会有什么问题?

更新:资源处置

正如 Samuel 在他的回答中指出的那样,有一个渠道处置问题,我想过但我忘了写。我打算做的是在程序终止时调用ThreadLocalDispose()希望这将调用底层IModels 的Dispose()。虽然我将不得不验证,因为ThreadLocal documentation 没有指定它是否会处理 undelying 对象(它们是否应该实现 IDisposable)。

这会带来“悬空”连接的危险,即特定线程的连接不再运行。虽然我不认为这是一个严重的问题,因为所有 TextQueueTransmitter 实例都旨在成为长期存在的对象,并且我不会过度创建线程。

【问题讨论】:

    标签: c# multithreading rabbitmq thread-local-storage


    【解决方案1】:

    我预见到的最大问题是不处理模型和泄漏资源。您需要控制它们的创建时间并适当地处理它们。

    【讨论】:

    • +1 提醒我忘记了一件非常重要的事情。 :) 我已经更新了我的问题,因此您可能想重新审视并详细阐述您的想法。
    最近更新 更多