Повторное использование new для того же объекта в C#

#c# #new-operator

#c# #new-operator

Вопрос:

 namespace usenewagain
{
    class Program
    {
        public static Thread thread1;

        static void Main(string[] args)
        {

            thread1 = new Thread(() => threadsDelegate(TimeSpan.FromMinutes(1), 1) );
            thread1.Start();

            while(thread1.IsAlive)
            {

            }

            thread1 = new Thread(() => threadsDelegate(TimeSpan.FromMinutes(2), 1));
            thread1.Start();

            while(thread1.IsAlive)
            {

            }

            Console.WriteLine("Done...");
            Console.ReadLine();
        }
    }
}
  

Насколько я могу судить по этой консольной программе, использование new в thread1 снова является законным, и, похоже, оно работает нормально. Насколько я могу судить, thread1 перезаписывается вторым вызовом new . Могу ли я получить некоторую проверку того, что повторное использование new допустимо таким образом?

Спасибо…

Ответ №1:

Да и нет.

каждый раз, когда вы используете new , вы создаете новый объект и сохраняете ссылку на этот объект в своей переменной.

Итак

 thread1 = new Thread(...)  
  

создает новый экземпляр Thread и сохраняет ссылку на этот экземпляр thread1 .


когда вы делаете это во второй раз, вы создаете второй экземпляр Thread , но не уничтожаете старый. Вы просто перезаписываете ссылку, которая является просто «адресом» потока.

однако у вас есть сборщик мусора, который очистит первый поток, если у вас нет ссылок на него, поэтому, если где-то останется ссылка на ваш первый поток (например, если вы назначили его какой-либо другой переменной), сбор мусора не будет.

Комментарии:

1. Так что, возможно, запуск GC. Сбор может помочь тогда?

2. @user2209542 нет, это не поможет. Даже если вы запустите GC. Сбор, если все еще есть ссылка на поток, он не будет собран. Лично мне нравится избегать ручной сборки мусора и позволять сборщику мусора делать это.

3. Таким образом, нет другой ссылки только на thread1, поэтому вы должны сказать, что проблемы нет, и thread1 в этом случае будет собираться мусор.

Ответ №2:

Если под «Допустимым» вы подразумеваете «Будет компилироваться» и «Перезапишет мою переменную», то да, это допустимо.

Однако это опасно. Перезаписывая переменную, вы теряете любую ссылку на нее, если хотите выполнить Join с ней или любую другую операцию. Если вы ожидаете, пока поток Join завершится , что, кстати, предпочтительнее вашего ожидания вращения, это безопасная операция.

Комментарии:

1. * спин-ожидание. Блокировка вращения — это нечто другое.

2. @dcastro, отличная точка зрения. Блокировка вращения используется для предотвращения условий гонки. Ожидание вращения просто тратит циклы процессора на ожидание завершения чего-либо еще.