2012-04-08 3 views
0

Я создал библиотеку Messenger, и я сделал ее потокобезопасной, поэтому ее можно обменивать между потоками, не беспокоясь. В основном я использую класс Monitor.Путаница о синхронизации потоков, когда два потока вызывают один и тот же метод

У меня есть процедура Logout, которая может занять некоторое время, потому что она пытается дождаться транзакций, прежде чем она выключит сокет и т. Д. Она асинхронна и имеет методы Begin/End, но для этого примера мы просто притворитесь, что это синхронно.

Что делать, если два потока вызывают выход из системы, один за другим? Что мне делать со вторым потоком?

В настоящее время я блокирую (используя Monitor.Wait, чтобы ждать Pulse от первого потока), пока первый выход не завершится, а затем выбросить AlreadyLoggedOutException.

Я также играл с созданием исключения LogoutInProgress, если вызывается Logout, но выход из системы уже происходит.

Оба, похоже, имеют преимущества и недостатки, но я хотел бы знать, что лучше всего думают другие люди.

ответ

2

Что является лучшим вариантом из двух вы упомянули, зависит от того, как вы хотите, чтобы ваша библиотека вела себя.

Я бы не выбрасывал исключение для потребителя и просто не запускал асинхронное событие/метод выхода из системы для обоих потоков при завершении фактического выхода из системы. Какой примитив синхронизации, который вы должны использовать для достижения этого, зависит от дизайна вашего метода/библиотеки. Возможно, если вы расскажете больше о методе Begin End, о котором вы упомянули, я смогу предложить лучше.

Этот вариант будет легче программировать.

+0

Асинхронная сторона этого не имеет значения. То, что вы говорите, что метод Logout должен просто вернуть (void) для обоих из них ПОСЛЕ выхода из системы без каких-либо исключений? – NoPyGod

+0

Если оба они намереваются выйти из одного клиента, а операция идемпотентна, тогда нет смысла бросать исключение. –

+0

Логика с исключением имеет смысл. Но вы действительно считаете, что оба выхода из системы должны «блокироваться» до тех пор, пока не завершится фактический выход из системы? Теоретически я мог бы просто вернуться со второго выхода из системы, так как в какой-то момент завершение кулака будет успешным. Проблема, которую я вижу в этом, заключается в том, что она дала бы вызывающей стороне иллюзию завершения Logout, когда она все еще имеет место. – NoPyGod

0

Существует третий вариант: второй поток, пытающийся выйти из системы, может обнаружить, что выход из системы уже произошел и ничего не делает. Если в договоре «Выход» есть «либо гарантировать, что пользователь вышел из системы, либо выбросил», тогда вы действительно должны сделать Logout idempotent.

Однако, если вы не можете терпеть множественные отходы, потому что это была бы логическая ошибка, вы как-то должны выбросить исключение.