C# 动态关键字和线程安全

标签 c# dynamic thread-safety zeromq

如果人们想看一下,请编辑这里的 github 页面 https://github.com/brandongrossutti/EventStore

我遇到了一个非常奇怪的问题,无法弄清楚根本原因。 我在自己的线程上有一个 Zeromq 订阅者。 当它收到消息时,它会调用委托(delegate),然后进入消息处理程序,最终进行此动态调用

    private void OnEvent(IEvent @event, bool isNew)
    {
        string eventName = "On" + @event.GetType().Name.Replace("Event", "");
        dynamic inheritingClass = this;
        MethodInfo method = inheritingClass.GetType().GetMethod(eventName);
        method.Invoke(inheritingClass, new object[] { @event });
        if (isNew)_uncommitedEvents.Add(@event);
    }

它在调用时终止,调用堆栈和异常不显示任何内容。 如果我慢慢地走下去,它似乎工作得很好。很困惑。

提前致谢

编辑:

这是启动订阅者的线程的写得不好的代码

    private readonly IHandlerResolver _resolver;
    private readonly Thread _subscriberThread;

    public MessageSubscriber(OnTheWireBusConfiguration configuration, IHandlerResolver resolver)
    {
        _resolver = resolver;

        _subscriberThread = new Thread(RecieveMessages);
        _subscriberThread.Start(new object[] { configuration, resolver, new Action<Message>(ProcessMessage) });
    }

    private static void RecieveMessages(object o)
    {
        object[] obj = o as object[];
        OnTheWireBusConfiguration configuration = (OnTheWireBusConfiguration)obj[0];
        IHandlerResolver resolver = (IHandlerResolver)obj[1];
        Action<Message> handlerDelegate = (Action<Message>) obj[2];
        using (var context = new Context(configuration.MaxThreads))
        {
            using (Socket subscriber = context.Socket(SocketType.SUB))
            {
                subscriber.Subscribe("", Encoding.Unicode);
                subscriber.Connect("tcp://localhost:5565");

                while (true)
                {
                    byte[] buffer = subscriber.Recv();
                    Message message = (Message) configuration.Deserialize(buffer);
                    Console.WriteLine(message);
                    handlerDelegate(message);
                    //resolver.ExecuteHandler(message);
                }
            }
        }
    }

    public void ProcessMessage(Message message)
    {
       _resolver.ExecuteHandler(message);
    }

编辑#2 调用堆栈

GHI.EventRepository.dll!GHI.EventRepository.AggregateRoot.OnEvent(GHI.EventRepository.IEvent event, bool isNew) Line 39 C# GHI.EventRepository.dll!GHI.EventRepository.AggregateRoot.OnEvent(GHI.EventRepository.IEvent event) Line 29 + 0x12 bytes C# GHI.TestDomain.dll!GHI.TestDomain.Model.TestAggregateRoot.TestAggregateRoot(System.Guid id) Line 15 + 0x59 bytes C# GHI.TestDomain.dll!GHI.TestDomain.Handlers.CreateNewTestAggregateRootCommandHandler.HandleMessage(GHI.TestDomain.Messages.CreateNewTestAggregateRootCommand message) Line 20 + 0x62 bytes C# [Native to Managed Transition]
GHI.Bus.dll!GHI.Bus.HandlerResolver.ExecuteHandler(GHI.Bus.Message message) Line 40 + 0x95 bytes C# GHI.Bus.ZeroMQ.dll!GHI.Bus.ZeroMQ.MessageSubscriber.ProcessMessage(GHI.Bus.Message message) Line 48 + 0x38 bytes C# GHI.Bus.ZeroMQ.dll!GHI.Bus.ZeroMQ.MessageSubscriber.RecieveMessages(object o) Line 39 + 0x13 bytes C# mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x173 bytes
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xeb bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x3b bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart(object obj) + 0x5d bytes [Native to Managed Transition]
[Appdomain Transition]
[Native to Managed Transition]

如果更方便的话我可以将其发布到 Github 上

编辑 #4 感谢大家的帮助,很高兴我可以从那段代码中删除动态关键字。 动态不是问题,而是我锁定堆栈的方式,再次感谢您,我已经对提到动态问题的人投了赞成票,并将接受下面的答案

最佳答案

我不熟悉 Zeromq,但看看你的 OnEvent 方法,我没有看到 dynamic 是必要的。当您不使用 dynamic 并用此方法替换该方法时会发生什么?

private void OnEvent(IEvent @event, bool isNew)
{
    string eventName = "On" + @event.GetType().Name.Replace("Event", "");
    MethodInfo method = this.GetType().GetMethod(eventName);
    method.Invoke(this, new object[] { @event });
    if (isNew)_uncommitedEvents.Add(@event);
}

如果行为没有改变,那么问题可能出在其他地方。

(可能想要在 Invoke 周围添加 if(method != null),除非您绝对确定它始终存在。)

关于C# 动态关键字和线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10081508/

相关文章:

javascript - 是否可以在 Javascript 中动态设置我想绑定(bind)的事件?

c++ - 在 MinGW 中使用线程?

python - 静态方法和线程安全

c# - Oracle 数据库 - ORA-01460 - 请求的转换未实现或不合理

java - 动态添加带有引用的 MenuItem

c - 在 C 中使用动态内存

c# - lock 和 monitor 可以安全地用在同一个对象上吗?

c# - 以编程方式查找 Silverlight 版本和安装文件夹

c# - ReadonlyCollection,对象是不可变的吗?

c# - Office (Outlook) 插件和 EXE 文件