С#, выходящий из блока using() с потоком, все еще выполняющимся на объекте с областью
Что происходит с потоком, если он запускает метод в объекте, который был освобожден при выходе из используемого блока?
Пример:
using (SomeObject obj = new SomeObject ())
{
obj.param = 10 ;
Thread newThread = new Thread(() => { obj.Work(); });
newThread.Start();
}
...
obj.Work() работает в новом потоке, но obj - объект IDisposable, который обычно освобождается при выходе из блока использования. Что произойдет, если поток продолжит работу после завершения использования блока? Будет ли объект удаляться только после завершения потока? Или сломается нить?
Спасибо.
Ответы
Ответ 1
Интересные вещи произойдут.
В частности, вызывается метод dispose на SomeObject, как до, так и после того, как Work был вызван, поскольку он может или не был запланирован для запуска этой точкой.
После этого это зависит от того, что делает метод dispose SomeObject; если он, скажем, выпускает SqlConnection, который не используется в "Работе", тогда не должно быть проблемы; если, однако, SomeObject ожидает, что он не был удален, у вас, вероятно, будет исключение, созданное в этом потоке.
Ответ 2
Помните, что IDisposable
- это всего лишь шаблон и не освобождает память, связанную с объектом. В таком случае закрытие блока using
вызовет obj.Dispose
, а другой поток, использующий obj
, продолжит выполнение.
Это создаст странные проблемы для вас, поскольку состояние obj's
может быть изменено, пока другой поток использует его (все зависит от способа реализации метода Dispose
). Излишне говорить, что это приложение IDisposable
, threading и оператора using
будет в лучшем случае проблематичным.
Ответ 3
Объект вызовет Dispose в конце блока. Он будет продолжать работать, но obj станет неустойчивым, так как Dispose предполагает закрыть соединения и т.д. Теперь возможно, что obj будет настроен для проверки того, что что-то используется и затем закрывает его, но я не буду рассчитывать на это, если вы написали объект, чтобы справиться с этим.
Ответ 4
Когда блок использования выходит из основного потока, он будет .Dispose() объект, который может вызвать всевозможные забавные проблемы concurrency. Однако объект не будет собирать мусор - он останется, но в недопустимом состоянии, в зависимости от вашей реализации .Dispose().