1

Тема: Чому прога зависає??

class Woot
{
    private static float PI;
    private static bool initialized = doInitialize();

    private static bool doInitialize()
    {
        if (!initialized)
        {
            var thread = new Thread(() => { PI = 3.14f; });
            thread.Start();
            thread.Join(); // Зависає тут
        }
        return true;
    }

    public static void Main(string[] args)
    {
        Console.WriteLine(PI);
    }
}

Що, потік не стартує допоки усі статичні об'єкти не ініціалізовані?

2

Re: Чому прога зависає??

Бо так робити не можна. Почнемо з питання: чи має виконатися умова в рядку 8, на вашу думку, і чому?

3 Востаннє редагувалося Yola (06.04.2015 13:40:54)

Re: Чому прога зависає??

koala написав:

Бо так робити не можна. Почнемо з питання: чи має виконатися умова в рядку 8, на вашу думку, і чому?

Обов'язково повинна виконуватись, бо статичний констуктор ініціалізує змінну в нуль/хиба. А викличиться статичний конструктор:

  • за до першого звертання до статичного члену класу,

  • створення об'єкта класу.

4

Re: Чому прога зависає??

Yola написав:
koala написав:

Бо так робити не можна. Почнемо з питання: чи має виконатися умова в рядку 8, на вашу думку, і чому?

Обов'язково повинна виконуватись, бо статичний констуктор ініціалізує змінну в нуль/хиба. А викличиться статичний конструктор за до першого звертання до члену класу.

Я один його не бачу?

Подякували: Yola1

5 Востаннє редагувалося Yola (06.04.2015 13:54:34)

Re: Чому прога зависає??

quez написав:

Я один його не бачу?

У C# у кожного класу є статичний і примірниковий конструктори.

Такий код породжує проміжний код у вкладенні

    internal class A
    {
    }

Хоча в картинці не видно статичного конструктора, але якійсь він повинен бути, бо інакше хто ж встановлює змінні в нуль.

--------------------------------------------------------------

Отже, статичний конструктор не завжди існує, тут quez правий. якщо подивитись на додане зображення, то можна побачити прапорець beforefieldinit який відповідає за ініціалізацію полів класу. Навіть для того, щоб відкласти якомога цю ініціалізацію іноді вставляють порожній статичний конструкор, тоді компілятор не генерує цей прапорець.

Post's attachments

Untitled.png 1.37 kb, 209 downloads since 2015-04-06 

6

Re: Чому прога зависає??

Як я розумію, під час роботи doInitialize (точніше, операція присвоювання) неявно блокує клас, щоб змінити initialized, а doInitialize лягає спати в очікуванні на thread, а thread має змінити PI і тому теж лягає спати, доки клас не відпустять.
Коротше - не можна так робити.

Подякували: Yola, leofun012

7 Востаннє редагувалося Yola (06.04.2015 15:25:56)

Re: Чому прога зависає??

Імовірно в метаданих ще нестворився об'єкт класу. Він ще не ініціалізувався, отже його не можна використовувати.

Тобто конструктор викликається після того як всі поля вже ініціалізовані. doInitialize викликається під час інітіалізації полів, ще до можливого виклику конструктора, тобто, якби існував статичний конструктор, то виклик до нього був би після виклику doInitialize. Ось чому об'єкт класу ще не готовий до використання.

8

Re: Чому прога зависає??

Так не виходить - ви ж звертаєтеся до initialized до формування статичної частини класу, і все працює. Ні, тут проблема саме у взаємному блокуванні потоків. Зробіть thread статичним і робіть Join в Main - все працюватиме.

Подякували: leofun011

9

Re: Чому прога зависає??

Дійсно, річ у тім, що CLR блокує клас під час роботи статичного конструктора. Це робиться, щоб не дати можливість різними потокам ініціалізувати клас двічі. А це уможливлює взаємоблокування.

Подякували: leofun011