Я должен звонить Близко () на ManualResetEvent?

Я читал на Поточной обработке.NET, и работал над некоторым кодом, который использует ManualResetEvent. Я нашел много примеров кода в Интернете. Однако при чтении документации для WaitHandle, я видел следующее:

WaitHandle реализует Расположить шаблон. Посмотрите, что Реализация Завершает и Располагает для Чистки Неуправляемых ресурсов.

Ни один из образцов, кажется, не называет.Close () на объектах ManualResetEvent, которые они создают, даже хорошая статья Recursion и Concurrency из блога pfxteam (Редактирование - это имеет блок использования, который я пропустил). Этот справедливый контроль в качестве примера, или не нужен? Мне любопытно, потому что WaitHandle "инкапсулирует операционные системные конкретные объекты", таким образом, могла легко быть утечка ресурсов.

15
задан Kevin Hakanson 10 February 2010 в 03:58
поделиться

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();
}
11
ответ дан 1 December 2019 в 00:59
поделиться

Close обрабатывается внутри ManualResetEvent Dispose и вызывается оператором using.

http://msdn.microsoft.com/en-us/library/yh598w02%28VS.100%29.aspx

2
ответ дан 1 December 2019 в 00:59
поделиться

Я часто использую ManualResetEvent и не думаю, что когда-либо использовал его внутри отдельного метода - это всегда поле экземпляра класса. Поэтому using() часто не применяется.

Если у вас есть поле экземпляра класса, которое является экземпляром ManualResetEvent, сделайте свой класс реализующим IDisposable и в своем методе Dispose() вызовите ManualResetEvent.Close(). Затем во всех случаях использования вашего класса вам нужно использовать using() или заставить содержащий класс реализовать IDisposable и повторять, и повторять...

2
ответ дан 1 December 2019 в 00:59
поделиться

Если вы используете ManualResetEvent с анонимными методами, тогда это очевидно полезно. Но, как упоминал Сэм, их часто можно передать рабочим, а затем установить и закрыть.

Я бы сказал, что это зависит от контекста того, как вы его используете - образец кода MSDN WaitHandle.WaitAll () дает хороший пример того, что я имею в виду.

Вот пример, основанный на образце MSDN, как создание WaitHandles с помощью оператора using будет исключением:

System.ObjectDisposedException
«Безопасный дескриптор был закрыт»

const int threads = 25;

void ManualWaitHandle()
{
    ManualResetEvent[] manualEvents = new ManualResetEvent[threads];

    for (int i = 0; i < threads; i++)
    {
        using (ManualResetEvent manualResetEvent = new ManualResetEvent(false))
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ManualWaitHandleThread), new FileState("filename", manualResetEvent));
            manualEvents[i] = manualResetEvent;
        }
    }

    WaitHandle.WaitAll(manualEvents);
}

void ManualWaitHandleThread(object state)
{
    FileState filestate = (FileState) state; 
    Thread.Sleep(100);
    filestate.ManualEvent.Set();
}

class FileState
{
    public string Filename { get;set; }
    public ManualResetEvent ManualEvent { get; set; }

    public FileState(string fileName, ManualResetEvent manualEvent)
    {
        Filename = fileName;
        ManualEvent = manualEvent;
    }
}
2
ответ дан 1 December 2019 в 00:59
поделиться

Вы заметите, что в коде

 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 по завершении работы, даже если код выбрасывает исключение.

2
ответ дан 1 December 2019 в 00:59
поделиться

Мне недавно отправили отрывок из C # 4.0 в двух словах: окончательная ссылка Джозеф Альбахари, Бен Альбахари. На странице 834 в Глава 21: Threading есть раздел, в котором говорится об этом.

Удаление дескрипторов ожидания

Закончив с дескриптором ожидания , вы можете вызвать его метод Close , чтобы освободить операционную систему {{1} } ресурс. В качестве альтернативы вы можете просто отбросить все ссылки на дескриптор ожидания и позволить сборщику мусора выполнить эту работу за вас когда-нибудь позже (дескрипторы ожидания реализуют шаблон удаления , при котором финализатор вызывает Close ). Это один из немногих сценариев, в которых использование этой резервной копии является (возможно) приемлемым, поскольку дескрипторы ожидания несут легкую нагрузку на ОС (асинхронные делегаты полагаются на именно этот механизм для освобождения дескриптора ожидания их IAsyncResult ).

Дескрипторы ожидания освобождаются автоматически, когда приложение выгружает домен.

21
ответ дан 1 December 2019 в 00:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: