静态成员不保留分配的值

发布于 2024-07-27 17:44:15 字数 929 浏览 2 评论 0原文

好的,我有一个静态类,它有两个静态成员,一个字符串和一个布尔值。
公共静态方法根据传入参数的状态为这些成员分配值。

然后调用私有静态方法来处理静态成员。

问题是,虽然布尔值保留了它在公共函数中设置的值,但字符串却没有。 它默认返回到其初始值。 这是为什么?
简化代码如下。

static class MessageHandler
{
    private static String m_messageToSend = String.Empty;
    private static bool m_requiresACK = false;


    public static void Send(String message)
    {
         //formatting etc (actual method sets more fields)
         m_messageToSend = message;
         m_requiresACK = true;

         Send();
    }

    private void static Send()
    {
        SendMessageDelegate sendDelegate = DoSend;
        //At this point m_requiresACK remains true but m_messageToSend does not 
        //hold value of message; it is empty.
        IAsyncResult ar = sendDelegate.BeginInvoke(m_messageToSend, m_requiresACK);


        //rest of function
    }
}

//some other class
MessageHandler.Send("Hello");

OK I have a static class that has two static members, a string and a boolean.
A public static method assigns values to these members based upon the state of parameters passed in.

A private static method is then called that processes the static members.

The problem is that while the boolean keeps the value it is set to in the public function, the string does not; it defaults back to its initialised value. Why is this?
Simplified code is below.

static class MessageHandler
{
    private static String m_messageToSend = String.Empty;
    private static bool m_requiresACK = false;


    public static void Send(String message)
    {
         //formatting etc (actual method sets more fields)
         m_messageToSend = message;
         m_requiresACK = true;

         Send();
    }

    private void static Send()
    {
        SendMessageDelegate sendDelegate = DoSend;
        //At this point m_requiresACK remains true but m_messageToSend does not 
        //hold value of message; it is empty.
        IAsyncResult ar = sendDelegate.BeginInvoke(m_messageToSend, m_requiresACK);


        //rest of function
    }
}

//some other class
MessageHandler.Send("Hello");

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

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

发布评论

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

评论(5

寂寞花火° 2024-08-03 17:44:15

此代码的线程“不安全性”可能是问题所在,因为当您的线程当前处于同一方法的中间时,其他线程可能会调用 Send(string)。 我建议对 Message 类进行以下重写:

static class Message
{
    public static void Send(String message)
    {
         Send(message, true);
    }

    private void static Send(string messageToSend, bool requiresACK)
    {
        SendMessageDelegate sendDelegate = DoSend;
        IAsyncResult ar = sendDelegate.BeginInvoke(messageToSend, requiresACK);

        //rest of function
    }
}

The thread "unsafetyness" of this code could be the problem, since other threads could call Send(string) while your thread is currently in the middle of the same method. I would suggest the following rewrite of the Message class:

static class Message
{
    public static void Send(String message)
    {
         Send(message, true);
    }

    private void static Send(string messageToSend, bool requiresACK)
    {
        SendMessageDelegate sendDelegate = DoSend;
        IAsyncResult ar = sendDelegate.BeginInvoke(messageToSend, requiresACK);

        //rest of function
    }
}
影子的影子 2024-08-03 17:44:15

这很可能是由于另一个线程调用

Message.Send("");

或您的 AppDomain 正在被卸载。 如果没有更多信息,很难确定。

This is most likely due to another thread calling

Message.Send("");

or your AppDomain is being unloaded. Without more information it is hard to say for sure.

挽清梦 2024-08-03 17:44:15

那里有一些巨大的线程安全问题。 如果你真的想要这个静态,有一个厚颜无耻的修复:

[ThreadStatic]
private static String m_messageToSend = String.Empty;
[ThreadStatic]
private static bool m_requiresACK = false;

它现在充当静态,但每个线程。 危机得以避免; 但这有点……好吧,我自己会尽力避免这种需要 - 但它会很好地工作。

重要:初始化器是针对每个线程的,而不是针对每个请求的; 由于您的线程很可能会被重复使用,因此您应该确保在尝试使用它之前初始化状态,否则您可能会遇到旧的垃圾。

You have some huge thread safety issues there. If you really want this static, there is a cheeky fix:

[ThreadStatic]
private static String m_messageToSend = String.Empty;
[ThreadStatic]
private static bool m_requiresACK = false;

This now acts as static, but is per-thread. Crisis averted; but this is a bit... well, I would try to avoid the need, myself - but it will work fine.

important: the initializers are per thread, not per request; since it is likely that your threads will get re-used, you should be sure to initialize the state before trying to use it, or you could have old garbage.

黯淡〆 2024-08-03 17:44:15

如果一个字段保持相同的值,而另一个字段没有,我会感到非常惊讶。

如果这是一个 Web 应用程序,那么如果应用程序被回收,就会发生这种情况。

I would be very surprised if one field would keep the same value, and the other didn't.

If this is a web application, this can happen if the application is recycled.

染年凉城似染瑾 2024-08-03 17:44:15

我在您的评论中看到,在第一行之后,私有变量为空,而不是保存参数的值。 当您点击 Send() 的第一行时,这是真的吗?

编写一个单元测试或一个简单的测试工具来调用 Message.Send("Hello World"); 并对输出进行断言。 将其与您的调用代码库隔离可以揭示是否是您的 Message 类行为异常,或者是否是消费者发送了错误/意外的数据。

另外,除非您的 //rest of function 包括重置您的 bool,否则在发送第一条消息后它将始终为 true。

I see in your comments that after that first line, the private variable is empty instead of holding the value of the parameter. Is this true as soon as you hit the first line of Send() ?

Write a unit test or a simple test harness that calls Message.Send("Hello World"); and does an assert on the output. Isolating this from your calling codebase could shine light on whether it is your Message class that is behaving abnormally, or if it is a consumer sending bad/unexpected data.

Also, unless your //rest of function includes resetting your bool, it will always be true after the first message is sent.

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