C # - поле класса является пустым при доступе из рабочего потока, но не из основного потока - PullRequest
2 голосов
/ 31 марта 2010

Не уверен, что я делаю не так:

class MyClass
{

    private EventInfo eventInfo;

    public void OnGenerateEvent(object sender, EventArgs e)
    { 
        // Called from *main* thread 

        // Load assembly and set eventInfo here
        eventInfo = ....GetEvent(...);
        eventInfo.AddEventHandler(source, handler);

        // Call to a static method in another assembly
        someMethodInfo.Invoke(null, null);

    }


    public void OnEventChanged(object sender, EventArgs args)
    {    
        // Called from a *worker* thread created 
        // by that static method in the other assembly

        eventInfo is null here !   

        // Trying to remove handler
        eventInfo.RemoveEventHandler(.....);

    }


    // But...
    protected override void Dispose(bool disposing)
    {
        // Called from *main* thread when program closes

        eventInfo is *not* null here
    }
}

Ответы [ 2 ]

5 голосов
/ 31 марта 2010

Я думаю, что нам нужно увидеть воспроизводимый код, но я вижу 4 сценария:

  • вы говорите с другим MyClass экземпляром в двух случаях - моя ставка здесь
  • у вас есть переменная с именем eventInfo в одном из методов (попробуйте использовать this.eventInfo, когда вы имеете в виду поле, если есть неопределенность)
  • запись или чтение кэшируются (попробуйте пометить поле volatile; опять маловероятно)
  • специфичное для потока поле (локальное хранилище) - очень маловероятно

Первые два гораздо более вероятны.

3 голосов
/ 31 марта 2010

Вам необходимо выполнить хотя бы одно из следующих действий:

  • делает eventInfo энергозависимым, чтобы OnGenerateEvent() записывал его в память до вызова someMethodInfo.Invoke()

  • использовать что-то вроде мьютекса / блокировки для защиты доступа к eventInfo. Это также обеспечит надлежащие барьеры памяти (это то, что действительно должно быть сделано по моему мнению)

О, и я предполагаю, что на самом деле не задействовано 2 разных MyClass экземпляра - это невозможно проверить с помощью показанного вами кода.

...