2013-09-17 2 views
0

Грубый контекст: система обмена сообщениями, Communicator отправляет сообщения (увеличивает поле _messagesInTransmission), получает ACK или NAK в другой поток (уменьшается _messagesInTransmission).Execute Dispose, только если переменная равна нулю

Если экземпляр Communicator установлен, он должен остановить свой базовый экземпляр транспорта, как только _messagesInTransmission ударит в нуль в следующий раз.

Как реализовать это поточно-безопасным способом?

public void Dispose() 
{ 
    _state = State.Stopping; // immediately change state in order to prevent additional messages to be sent 

    // TODO: wait for _messagesInTransmission to become zero 
} 

Поддерживает ли .NET Framework эту задачу?


Простое решение будет некоторое время (_mIT! = 0) петли и некоторые Thread.Sleep, однако, я хочу писать более привлекательным код, если это возможно.

+0

Передача сообщения происходит в другом потоке? – Jacob

+0

Скорее всего, я использую фреймворк на базе Microsoft CCR под капотом. –

+1

Имейте в виду, что в руководстве по внедрению 'IDisposable' указано, что на один и тот же объект должны быть разрешены несколько вызовов' Dispose'. –

ответ

1

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

Также убедитесь, что ваш рабочий поток создан с IsBackground установлен в true. Таким образом, когда ваше приложение закроется, оно обязательно будет завершено.

3

Вы действительно не хотите делать это на Dispose().

Рассмотрите ситуацию, когда ваше приложение-получатель аварийно завершает работу и никогда не вызывает одно из сообщений ACK/NACK. Вы не получите достаточного количества ответов на нуль счетчика, и когда вызывается dispose, возможно, во время GC или блока using(...){...}, он будет вешать бесконечно.

Я бы предложил переместить эту функциональность на другой метод, который называется OnStop().

И просто держать свой метод Dispose() для очистки ресурсов, закрытие соединений и т.д. ...

+0

Я думаю о тайм-ауте, чтобы предотвратить неопределенное зависание, в случае достижения тайм-аута я могу зарегистрировать ошибку. –

+1

Хорошая точка на подвесе –

1

«поточно» способ сделать это (и как такие вещи, как FileStream ручкой она) должен иметь метод Flush() который блокирует запись всех ожидающих записей. Как только у вас есть это, вам просто нужно вызвать Flush() внутри метода Dispose().

Теперь это приведет к блокировке Dispose(), но знаешь что? Мы хотим уничтожить! Если вы не блокируете при удалении во время выполнения работы, последняя ссылка на объект может быть выпущена (вероятно, произойдет в блоке using), и ваш объект будет иметь право на сбор мусора до того, как он будет обработан.

Смежные вопросы