private void Listen() { _listener.Start(); try { // Крутимся, пока слушатель активен while (_listener.IsListening) { // Оборачиваем в try, чтобы одним неудачным соединенем не убить приложение, мы же не node.js try { // Ждем соединения, поток заблокирован var context = _listener.GetContext(); /* * В этот момент слушатель снова может принимать соединения, * Но ему мешает код ниже, следовательно код ниже должен выполняться, * как можно, быстрее. * * Мы используем очередь подключений. * Будем просто добавлять поделючение в очередь, а потоки обработки будут * забирать их оттуда. У нас один писатель, однако, считается, что методы типа queue * непотокбезопасны, это может быть, например потому, что в процессе добавления перевыделяется * память и перемещаются данные, напомню, что массив нельзя увеличить или уменьшить на месте, * можно только перевыделить, Array.Resize делает именно это. * * Здесь будем ждать до посинения, потому что непонятно, что иначе делать с запросом. */ using (var lc = _lock.Acquire()) { _clientQueue.Enqueue(context); } } catch (Exception) { // Здесь предполагается логирование. } } } catch (ThreadAbortException) { // Здесь не делаем ничего и это, представь себе, в нашем случае -- норм, хотя, // в реальном приложении мы захотим добавить сюда сообщение о том, что что-то пошло не совсем так и // и сервер не остановился нормально. } // Закрываем соединения. _listener.Close(); }
protected override void ExecuteInner(IJobExecutionContext context) { var dataMap = context.MergedJobDataMap; if (!dataMap.ContainsKey(DataMapKey)) { throw new DataMapKeyMissingException(string.Format("Unique job identifier key missing in mergeddatamap. Please include it with a unique identifier/id assigned. E.g. {0}:12345", DataMapKey)); } string identifier; if ((identifier = dataMap[DataMapKey] as string) == null) { throw new DataMapIdentifierNullException(string.Format("Key {0} not present in mergeddatamap. Please include this key with a unique identifier/id assigned", DataMapKey)); } using (var handle = _lock.Acquire(GetLockHeader + identifier, TimeSpan.FromSeconds(5))) { if (handle.AcquisitionFailed) { throw new LockAcquisitionException(string.Format("Lock {0} could not be acquired. There was another operation using the same lock currently running", GetLockHeader + identifier)); } // do your shit ExecuteInnerInner(context); } }
/// <summary> /// Выполняет что-то, если к моменту захвата блокировки выполняется условие /// </summary> public static void ExecuteIf(this ILock @this, Func <bool> condition, Action code) { using (var lc = @this.Acquire()) { if (!condition() || !lc.IsTaken) { return; } code(); } }
/// <summary> /// Выполняет что-то, если блокировку удалось захватить /// </summary> public static void Execute(this ILock @this, Action code) { using (var lc = @this.Acquire()) { if (!lc.IsTaken) { return; } code(); } }