Нужно ли мне вызывать Close () на ManualResetEvent?
Я читал на .NET Threading и работал над некоторым кодом, который использует ManualResetEvent. Я нашел много примеров кода в интернете. Однако, при чтении документации для объекта waithandle, я увидел следующее:
WaitHandle реализует Dispose узор. См. раздел внедрение Finalize и Dispose для очистки неуправляемых Ресурсы.
ни один из образцов, кажется, называют .Закрыть () на ManualResetEvent объекты, которые они создают,даже приятно рекурсия и параллелизма статья из блога pfxteam (редактировать - это с помощью блока я пропустил). Это просто пример надзора, или не нужен? Мне любопытно, потому что WaitHandle "инкапсулирует объекты, специфичные для операционной системы", поэтому может легко произойти утечка ресурсов.
6 ответов
в общем случае, если объект реализует IDisposable
он делает это по причине, и вы должны назвать Dispose
(или Close
, в зависимости от случая). В Примере, который вы размещаете, ManualResetEvent обернут внутри using
оператор, который будет" автоматически " обрабатывать вызов Dispose
. В этом случае Close
синоним Dispose
(что верно в большинстве IDisposable
реализации, которые обеспечивают Close
метод).
код пример:
using (var mre = new ManualResetEvent(false))
{
...
}
увеличивается до
var mre = new ManualResetEvent(false);
try
{
...
}
finally
{
((IDispoable)mre).Dispose();
}
Мне недавно переправили отрывок из C# 4.0 в двух словах: окончательная ссылка От Joseph Albahari, Бен Albahari. На странице 834, в Глава 21: Нарезание Резьбы есть раздел, говорящий об этом.
Утилизация Дескрипторов Ожидания
Как только вы закончите с ожиданием ручка, вы можете назвать его закрыть способ чтобы освободить операционную систему ресурс. Кроме того, вы можете просто отбросьте все ссылки на ожидание ручка и разрешить сборщик мусора чтобы сделать работу за вас позже (дескрипторы ожидания реализуют удаление шаблон, по которому вызывается finalizer закрыть). Это один из немногих сценарии, в которых используется эта резервная копия (возможно) приемлемо, потому что подождите ручки имеют легкую нагрузку на ОС (асинхронные делегаты полагаются на именно этот механизм выпустить их объекта iasyncresult это ждать ручки).
дескрипторы ожидания освобождены автоматически, когда приложение домен выгружается.
закрытие обрабатывается внутри инструкции Manualresetevent Dispose, и это вызывается инструкцией "using".
http://msdn.microsoft.com/en-us/library/yh598w02%28VS.100%29.aspx
вы заметите код
using (var mre = new ManualResetEvent(false))
{
// Process the left child asynchronously
ThreadPool.QueueUserWorkItem(delegate
{
Process(tree.Left, action);
mre.Set();
});
// Process current node and right child synchronously
action(tree.Data);
Process(tree.Right, action);
// Wait for the left child
mre.WaitOne();
}
использует ключевое слово' using'. Это автоматически вызывает метод dispose по завершении, даже если код создает исключение.
я использовал ManualResetEvent
много и не думаю, что я когда-либо использовал его внутри одного метода-это всегда поле экземпляра класса. Поэтому using()
часто не применяется.
если у вас есть поле экземпляра класса, который является экземпляром ManualResetEvent
, сделайте свой класс implement IDisposable
и в Dispose()
вызов метода ManualResetEvent.Close()
. Тогда во всех обычаях вашего класса вам нужно использовать using()
или сделайте содержащий класс implement IDisposable
и повторять, и повторять...
Если вы используете ManualResetEvent
с анонимными методами, то это явно пригодится. Но, как упоминал Сэм, их часто можно передать рабочим, а затем установить и закрыть.
Так что я бы сказал, что это зависит от контекста использования - MSDN WaitHandle.WaitAll() пример кода имеет хороший пример того, что я имею в виду.
вот пример, основанный на примере MSDN о том, как создание WaitHandles с using
заявление исключение: