Нужно ли мне вызывать 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 заявление исключение: