Переключение на Главную Страницу Страницы: 1 ... 5 6 [7] 8 9 ... 11 ОтправитьПечать
Очень популярная тема (более 25 ответов) Перехватчик. Для каких событий необходим ручной вызов оригинального? (число прочтений - 78262 )
Dmitry The Wing
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 839
Местоположение: Где-то в Сибири
Зарегистрирован: 18. Августа 2009
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #90 - 26. Января 2011 :: 01:56
Печать  
zk96 писал(а) 25. Января 2011 :: 19:10:
2 Dmitry The Wing
Активизируй документ в журнале ПослеСозданияФормы.

Проверил. Это работает, однако это обход проблемы, а не ее исправление...
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #91 - 26. Января 2011 :: 12:39
Печать  
Интересное замечание:

Код
Выбрать все
Процедура НазначитьКонтекст(Конт) Экспорт
	рез = Сам(Контекст).ЗаменитьБазовыйОбъект("Документ", Конт);

	Если ТипЗначенияСтр(Конт) = "ГрупповойКонтекст" Тогда
		Попытка Форма = Конт.Форма; Исключение Возврат; КонецПопытки;
		оПерехватчик = СоздатьОбъект("ТПерехватчик.Документ");
		оПерехватчик.Инит(Конт, Сам(Контекст));

		Перехватчик = СоздатьОбъект("Перехватчик");
		Перехватчик.ПерехватитьСобытияГК(Конт, оПерехватчик);
	КонецЕсли;
КонецПроцедуры
 



Выделенная Попытка-Исключение нужны, чтоб отсечь вылет, если групповой контекст представляет собой не открытую форму документа, а контекст модуля проведения документа
(в этом случае Перехватчик.ПерехватитьСобытияГК() становится плохо).
А есть ли еще какой-нить способ различить эти 2 типа групповых контекстов?

PS я знаю, что у меня есть идеологическая ошибка в использовании перехватчика. Если придет время, когда я всерьез примусь за документы - будет большой рефакторинг классов. ОЧЕНЬ большой. Улыбка
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #92 - 17. Февраля 2011 :: 06:47
Печать  
Код
Выбрать все
Функция Событие_ОбработкаПроведения(КонтДок, ПарамПроведения) Экспорт
	ЗапросСКЛ.УстановитьТекстовыйПараметр("Документ", КонтДок.ТекущийДокумент());
	ЗапросСКЛ.УстановитьТекстовыйПараметр("Статус", 0);
	идСтроки = ЗапросСКЛ.ВыполнитьСкалярный(тзп_ПроведениеНачало);

	Рез = Перехватчик.ВыполнитьСобытиеГК(, КонтДок, "ОбработкаПроведения", ПарамПроведения);

	ЗапросСКЛ.УстановитьТекстовыйПараметр("Результат", Рез);
	ЗапросСКЛ.УстановитьТекстовыйПараметр("идСтроки", идСтроки);
	ЗапросСКЛ.Выполнить(тзп_ПроведениеКонец);

	Возврат Рез;
КонецФункции
 



В таблицу статистики пишу некоторую информацию при проведении и отмене проведения.
Все бы хорошо, но выяснилось (ВНЕЗАПНО, ага), что если рез = 0, то таблица статистики вторым запросом апдейтится, а потом 1Ска делает rollback транзакции. (что, в принципе, естественно - просто об этом в момент написания данной функции я как-то не сообразил).
Но желание накапливать информацию о неудачных попытках проведения есть.
Я так понимаю, что для этого нужно не-родное соединение с 1Ской (но тогда получим затык при монопольном проведении).
Внимание, вопрос - можно ли как-то разрулить ситуацию?
Может, есть события "ПередПроведением"/"ПослеПроведения"?
  
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #93 - 17. Февраля 2011 :: 09:35
Печать  
Используй асинхронный вызов нужного тебе кода, например. через посылку внешнего события или через Таймер (ФормЕкс).
Т.е. если рез = 0, то посылаешь событие с минимальным таймаутом и твой обработчик вызовется уже после отмены проведения.

ЗЫ На всякий случай проверь работу таймаута при групповом перепроведении документов.
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer && tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #94 - 17. Февраля 2011 :: 09:38
Печать  
Satans Claws писал(а) 26. Января 2011 :: 12:39:
Интересное замечание:

Код
Выбрать все
Процедура НазначитьКонтекст(Конт) Экспорт
	рез = Сам(Контекст).ЗаменитьБазовыйОбъект("Документ", Конт);

	Если ТипЗначенияСтр(Конт) = "ГрупповойКонтекст" Тогда
		Попытка Форма = Конт.Форма; Исключение Возврат; КонецПопытки;
		оПерехватчик = СоздатьОбъект("ТПерехватчик.Документ");
		оПерехватчик.Инит(Конт, Сам(Контекст));

		Перехватчик = СоздатьОбъект("Перехватчик");
		Перехватчик.ПерехватитьСобытияГК(Конт, оПерехватчик);
	КонецЕсли;
КонецПроцедуры
 



Выделенная Попытка-Исключение нужны, чтоб отсечь вылет, если групповой контекст представляет собой не открытую форму документа, а контекст модуля проведения документа
(в этом случае Перехватчик.ПерехватитьСобытияГК() становится плохо).
А есть ли еще какой-нить способ различить эти 2 типа групповых контекстов?

PS я знаю, что у меня есть идеологическая ошибка в использовании перехватчика. Если придет время, когда я всерьез примусь за документы - будет большой рефакторинг классов. ОЧЕНЬ большой. Улыбка

Можно через Информатор проверить, если ли реквизит Форма у Контекста. в этом случае блок Попытка не нужен.

ЗЫ а вообще, конечно, лучше классы по целям разделять, т.е. не должен один класс/один объект обрабатывать перехват как событий формы, так и событий проведения или ГМ Улыбка Про это ты уже в курсе.
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer && tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #95 - 17. Февраля 2011 :: 09:46
Печать  
artbear писал(а) 17. Февраля 2011 :: 09:35:
Используй асинхронный вызов нужного тебе кода, например. через посылку внешнего события или через Таймер (ФормЕкс).
Т.е. если рез = 0, то посылаешь событие с минимальным таймаутом и твой обработчик вызовется уже после отмены проведения.

ЗЫ На всякий случай проверь работу таймаута при групповом перепроведении документов.


Ухххх, блин - тогда при Рез = 0 надо будет сначала выдрать инсертнутые данные, а потом (вместо апдейта) целиком инсертнуть подготовленную строку.

На самом деле, есть еще вариант выполнять запросы отдельным соединением, а таблицу хранить в соседней базе.
Учитывая наличие "заботливо" прикрученного прошлым программистом ТойСКЛ - наверное, даже особо извращаться не придется.
Правда, кажется, в монопольном режиме Той использует родное соединение - но монопольный режим используется крайне-крайне-крайне редко (т.е. практически никогда).


Цитата:
Можно через Информатор проверить, если ли реквизит Форма у Контекста. в этом случае блок Попытка не нужен.

ЗЫ а вообще, конечно, лучше классы по целям разделять, т.е. не должен один класс/один объект обрабатывать перехват как событий формы, так и событий проведения или ГМ Улыбка Про это ты уже в курсе.

Про информатор не догадался, ага.

А про классы - знаю, да. Там надо хорошенько сесть и продумать структуру классов.
Ибо а) должен быть управляющий класс, который создается как в форме, так и в модуле (в которм всякие алгоритмы проверок заполнения, ввода на основании и ты ды) и в виде
Код
Выбрать все
оДок = СоздатьОбъект("ТДокумент.<вид>");
оДок.НазначитьКонтекст(СоздатьОбъект("Документ.<Вид>")); 

который наследует от общего ТДокумент; и б) должен быть класс-перехватчик, который на штатные события (ВводНового(), ВводНаОсновании(), ПриЗаписи()) вызывал бы соответствующие методы управляющего класса. Ну и при этом количество копипастного кода должно быть минимальным.
В целом, оно примерно понятно, как все должно быть. Но в тот момент, когда это писалось, с перехватчиком только начал разбираться... в общем - получилось так, как получилось. Ркуи дойдут - сделаю большой рефакторинг структуры классов.


PS с этой багой еще не разбирался? http://www.1cpp.ru/bugs/show_bug.cgi?id=4524
  
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #96 - 17. Февраля 2011 :: 12:11
Печать  
Satans Claws писал(а) 17. Февраля 2011 :: 09:46:
PS с этой багой еще не разбирался? http://www.1cpp.ru/bugs/show_bug.cgi?id=4524

Нет, все силы уходят на 8-ку.
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
Dmitry The Wing
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 839
Местоположение: Где-то в Сибири
Зарегистрирован: 18. Августа 2009
Пол: Мужской
Перехватчик. ВыполнитьОригинальноеСобытиеГК. Нет информации об ошибке.
Ответ #97 - 24. Февраля 2011 :: 04:57
Печать  
Обнаружен глобальный косяк в функции ВыполнитьОригинальноеСобытиеГК!
Если в оригинальном обработчике возникла ошибка - перехватчик об этом не узнает, а это вызывает зависание при перехвате событий типа "ПриЗакрытии", т.е. невозможно закрыть форму.
Мною предполагалось, что возможен
Код
Выбрать все
	Если Рез > 0 Тогда
		Попытка
			Рез = Перехватчик.ВыполнитьОригинальноеСобытиеГК(КонтОбъекта, "ПриЗакрытии");
		Исключение
			Сообщить("Ошибка при вызове оригинального события ПриЗакрытии: " + ОписаниеОшибки());
			Рез = 1;
		КонецПопытки;
	КонецЕсли; 


Однако, исключения нет. есть только сообщение: Цитата:
Возникла ошибка в оригинальном обработчике события ПриЗакрытии

Вопрос: я что-то делаю не так? или это глобальный баг?
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #98 - 24. Февраля 2011 :: 11:10
Печать  
В общем-то, это известная вещь - если в процедуре "ПриЗакрытии" возникает необработанное исключение - то закрыть форму становится невозможно.


А перехват событий, похоже, сам оборачивает каждое перенаправление вызова в "Попытку".
(к тому же - он же по каким-то соображениям пишет "Возникло исключение в оригинальном обработчике события").

А должен ли он делать throw exception наружу - это, конечно, вопрос.
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #99 - 29. Августа 2011 :: 08:08
Печать  
Satans Claws писал(а) 17. Февраля 2011 :: 06:47:
В таблицу статистики пишу некоторую информацию при проведении и отмене проведения.
Все бы хорошо, но выяснилось (ВНЕЗАПНО, ага), что если рез = 0, то таблица статистики вторым запросом апдейтится, а потом 1Ска делает rollback транзакции. (что, в принципе, естественно - просто об этом в момент написания данной функции я как-то не сообразил).
Но желание накапливать информацию о неудачных попытках проведения есть.



Код
Выбрать все
Функция Событие_ОбработкаПроведения(КонтДок, ПарамПроведения) Экспорт
	Старт = ЗапросСКЛ.ВыполнитьСкалярный("SELECT convert(Char(23), GetDate(), 126)");

	Рез = Перехватчик.ВыполнитьСобытиеГК(, КонтДок, "ОбработкаПроведения", ПарамПроведения);

	Если Рез = 0 Тогда
		ЗапросСКЛ.Выполнить("Rollback Tran");
	КонецЕсли;

	ЗапросСКЛ.УстановитьТекстовыйПараметр("Документ", КонтДок.ТекущийДокумент());
	ЗапросСКЛ.УстановитьТекстовыйПараметр("Старт", Старт);
	ЗапросСКЛ.УстановитьТекстовыйПараметр("Статус", Рез);
	ЗапросСКЛ.ВыполнитьСкалярный(тзп_ПроведениеКонец);
	Если Рез = 0 Тогда
		ЗапросСКЛ.Выполнить("Commit Tran");
	КонецЕсли;

	глМенеджерСобытийДокументов.ПослатьСобытие(КонтДок, "Запись");

	Возврат Рез;
КонецФункции	// Событие_ОбработкаПроведения
 



Вроде, работает как нужно.
Внимание - вопрос: какие грабли я мог не заметить?

Проведение нового документа проверил - как минимум, не вылетает и обходится без веселых шизофрений (как, например, если открыть в событии ПриЗаписи() транзакцию, внутри тразакции сказать Записать(), а потом сделать откат транзации).
Единственно, что не могу сообразить: как штатно ведет себя 1Ска, если в новом документе нажимаем Провести, а в проведении возникает СтатусВозврата = 0;

У меня документ получается записан, не проведен.
В штатной 1С8 в такой ситуации он остается новым.
В штатных клюшках - ???
  
Наверх
 
IP записан
 
Dmitry The Wing
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 839
Местоположение: Где-то в Сибири
Зарегистрирован: 18. Августа 2009
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #100 - 29. Августа 2011 :: 08:20
Печать  
При нажатии "Провести" выполняются две операции: Записать и Провести. Видимо, статус возврата влияет только на вторую.
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #101 - 29. Августа 2011 :: 09:06
Печать  
Dmitry The Wing писал(а) 29. Августа 2011 :: 08:20:
При нажатии "Провести" выполняются две операции: Записать и Провести. Видимо, статус возврата влияет только на вторую.

Ну, все сходится к тому.
Значит, можно выпускать в релиз.
  
Наверх
 
IP записан
 
Dmitry The Wing
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 839
Местоположение: Где-то в Сибири
Зарегистрирован: 18. Августа 2009
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #102 - 29. Августа 2011 :: 09:12
Печать  
Вдогонку: в восьмерке нет отдельной операции проведения - там это часть операции записи.
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #103 - 29. Августа 2011 :: 09:39
Печать  
Тоже верно.
  
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Перехватчик. Для каких событий необходим ручной вызов оригинального?
Ответ #104 - 30. Августа 2011 :: 07:53
Печать  
Satans Claws писал(а) 29. Августа 2011 :: 09:06:
Dmitry The Wing писал(а) 29. Августа 2011 :: 08:20:
При нажатии "Провести" выполняются две операции: Записать и Провести. Видимо, статус возврата влияет только на вторую.

Ну, все сходится к тому.
Значит, можно выпускать в релиз.

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

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
Переключение на Главную Страницу Страницы: 1 ... 5 6 [7] 8 9 ... 11
ОтправитьПечать