![]() |
|
Модераторы: Partizan, gambit |
![]()
|
|
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
есть класс, который в любом методе может кинуть исключение.
Хотелось бы не засорять код try/catch, а передать в него метод, который бы вызывался при исключении. Как правило в этом методе необходимо остановить все потоки и сделать просто невидимыми кнопки. Еще бы хотелось в этот метод передать само исключение, чтоб можно было бы вывести сообщение об ошибке. Как это правильно сделать ? |
|||
|
||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 110 Всего: 232 |
Есть событие AppDomain.CurrentDomain.UnhandledException, генерится при необработанном исключении в рамках всего приложения.
-------------------- ![]() |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
||||
|
||||
| Naum |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 743 Регистрация: 7.9.2005 Где: Саратов, ул. Поса дского, 298 Репутация: 8 Всего: 15 |
Этот метод и есть обработчик события AppDomain.CurrentDomain.UnhandledException. -------------------- У нас всего два праздника Новый год и ТЯПница. |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
брр.... ничего не понял
|
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
мне нет необходимости ловить все исключения глобально. Нужно лишь ловить исключения от одного класса
Добавлено @ 16:42 кстати зачем вообще этот обработчик, если код
должен позволять это делать. Но как показала практика он этого не делает |
|||
|
||||
| awers |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 1465 Регистрация: 22.3.2006 Где: Россия, Таганрог Репутация: нет Всего: 31 |
zss, а с чего вдруг он будет ловить все исключения? он и ловит сам Application.Run.
а AppDomain.CurrentDomain.UnhandledException самый лучший способ .. |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
но ведь если исключение возникнет, то оно будет в первичном потоке приложения (или в порожденных потоках) А вообще может быть я не совсем туда копаю Я ловлю SocketException. Я хочу в методах при любой ошибке возвращать статус завершения, а лишь только если сокет закрылся или обрыв - тогда дергать метод в котором отработает нужный код. Еще правда не совсем понятно как отделить эти типы исключений друг от друга Добавлено @ 17:14 Еще не соасем понят как поступить с оэтим объектом, если из блока catch будет вызван метод, а в самом методе нужно прибить этот объект. Что можно здесь придумать ? |
|||
|
||||
| awers |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 1465 Регистрация: 22.3.2006 Где: Россия, Таганрог Репутация: нет Всего: 31 |
а вообще помоему непрально использовать общее исключение для всего. когда писал либу для использования MySQL, приходилось изголяться капитально:
А отсутствие Мускуль сервера - MySqlException не обрабатывает Это сообщение отредактировал(а) awers - 20.1.2007, 17:36 |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
но обработка всех типов исключений для каждого вызова метода это мне кажется еще большим извращением З.Ы. Что за идиот придумал бросать исключения в методах класса... |
|||
|
||||
| ivashkanet |
|
|||
![]() Кодю потиху ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3684 Регистрация: 23.2.2006 Где: Гомель, Беларусь Репутация: 47 Всего: 149 |
А где их еще бросать? По делу: Словить кинутое исключение может только сам метод либо метод, который находиться выше него в цепочке вызовов. Поэтому все точки входа в твой класс придеться оборачивать в try/catch. И ничего с этим не поделаешь Либо, как уже говорили, можно ловить событие AppDomain.CurrentDomain.UnhandledException. Но тогда это придеться настраивать во всех приложениях, которые будут работать с твоим классом (ИМХО), что не есть гуд |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
ivashkanet, а что если ловить исключения внутри класса и при критичных вываливать свое или например вызывать событие ?
|
|||
|
||||
| ivashkanet |
|
||||||
![]() Кодю потиху ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3684 Регистрация: 23.2.2006 Где: Гомель, Беларусь Репутация: 47 Всего: 149 |
Легко:
Но это все равно не избавит тебя от Try/Catch, т.е не поможет решить проблемму:
Добавлено @ 11:02 Которая, ИМХО, совсем не проблемма, а следствие ленности |
||||||
|
|||||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
да нет - я не неленив код обрабатывающий исключения и для пользователя класса будет меньше писать. Нужно лишь только обратотать сопытие при критической ситуации |
|||
|
||||
| zss |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
в общем примерно сделал
но появились проблеммы у меня есть класс в котором я обрабатываю исключения и вызываю событие если нужно. Пусть это класс A; у него например есть методы write и read, которые могут дернуть событие. Также есть класс B, который содержит А. Я создаю внутри В класс А и подписываюсь на сообщение.
теперь у меня в В есть поток, который вызывает методы класса А.
Если в потоке произойдет исключение в методе write или read, то будет вызвано событие OnMethod в котором я пытаюсь остановить поток. Вопрос: дождусь ли я его ? Добавлено @ 21:28 И если нет, то можно ли событие вызвать ассинхронно ? |
||||
|
|||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 110 Всего: 232 |
Смотри: есть метод, внутри которого предполагается наличие исключительных ситуаций. Имя этому методу write/read. Для того, чтобы обработать эти ситуации, метод который вызывает write/read, заключает вызовы этих методов в try...catch - и всё пучком... Пока мы не начинаем говорить о многопоточности. В этом случае, тот метод который реализует поток (MainThread), собственно и должен обработать исключение (делай "раз!") и сгенерировать событие (делай "два!"), если он предполагает подписчика на это событие. В данном случае, событие - это прикладная логика, предусматривающая внешний код, который реагирует на наличие исключительных ситуаций. Так или иначе, в любом случае обрабатывать исключения должен тот код, который: - а) сам генерирует исключения - б) вызывает код, генерирующий исключения В том и другом случае, речь всегда идёт об одном потоке. Ответственность за обработку исключений всегда берёт на себя тот, кто вызывает потенциально опасный код. То есть - это либо участок метода, заключенный в try..catch, либо мелкий кусок кода, заключенный в try..catch и вызывающий другой метод. -------------------- ![]() |
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 17 Всего: 59 |
Если само событие ты вызываешь из метода write() или read(), то метод обработки события будет вызываться в том же потоке, что и write/read. Метод m_thread.Join() без параметров, бесконечно ждет завершения потока, а в данном случае он никогда не дождется, так как вызывается из того же потока завершение которого он ждет (надеюсь понятно Добавлено @ 22:11 поясни подробней немного, наверняка нужен просто другой подход -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
блин... чтож дак все сложно.
Ладно - я все понял. Обработка должна быть при вызове методов, которые могут бросить исключение. Я тогда зайду с другой стороны. Как можно убить объект (или сказать его владельцу). Что его уже буссмысленно использовать и нужно создавать заново. Например если сокет закрылся, то класс, использующий его, использовать бесполезно. При этом нужно что-то сделать извне и заставить заново его создать. |
|||
|
||||
| -Mikle- |
|
|||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 17 Всего: 59 |
Типичная ситуация. Я всегда делал так: 1.Есть класc коллекция объектов mySockColl 2.Есть сам клас mySock использующий сокет, каждый mySock использует свой отдельный Socket 3.Созданием и удалением объектов mySock занимается объект mySockColl (при создании добавляет в коллекцию) 4.У класса mySock есть событие OnDisconnect 5.На этом событие висит метод OnDisconnectHandler(...) в mySockColl 6.Этот метод убивает mySock (получаем от аргумента object sender) и удаляет из коллекции экземпляр mySock (sender) Далее все просто, в самом mySock можно сделать метод, например, void pingSocket(), который проверяет закрылся ли сокет. Если да, то вызвать событие OnDisconnect. Вызывать метод pingSocket() можно перед отправкой или получением данных из сокета. (Вроде-бы я ничего не упустил Добавлено @ 22:42 И вообще, помоему, тема уже переросла в другой раздел -------------------- Если тебе плюют в спину, значит ты впереди... |
|||
|
||||
| ivashkanet |
|
||||
![]() Кодю потиху ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3684 Регистрация: 23.2.2006 Где: Гомель, Беларусь Репутация: 47 Всего: 149 |
Срочно читать про события и мультикаст делегаты Вызывая MyEvent(this, e) ты всего лишь по очереди вызываешь методы, зарегистрированные в мультикаст делегате, с одними и теме же параметрами. А так как выполнение инструкций самого метода выполняет поток его вызвавший, то эти методы будут выполняться в том же потоке. В Multicast delegat (делегат на метод возвращающий void) можно регистрировать много методов (объединять их в одну связку). После чего, при вызове делегата, будут вызваны все методы, которые были зарегестрированы (объеденены) в делегате. Евент от делегата отличается только тем, что имеет более удобный способ регистрации методов:
Может где-то я здесь наврал, но суть верна Пример:
|
||||
|
|||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
-Mikle-, интересная идея. Тоесть я создаю mySock и подписываюсь у него на событие OnDisconnect.
1. Это схоже с тем, что я впринципе хотел 2. Зачем тогда коллекция ? Достаточно создать класс и самому отслеживать время его жизни. (как правило редко нужно несколько сокетов) 3. Что будет если это событие вызвано из другого потока (про что я и говорил выше - или коллекция это может решить ?) 4. Как пингонуть сокет ? 5 Может у Socket уже есть событие на закрытие ? 6 Какой код ошибки позволит узнать, что исключение было вызванно именно из-за закрытия сокета ? Добавлено @ 09:28
и что это такое ? Это сообщение отредактировал(а) zss - 23.1.2007, 09:56 |
|||
|
||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
а если через делегат вызвать AbortThread ? |
|||
|
||||
| -Mikle- |
|
||||||||
![]() Невидимка Vingrad'а ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1672 Регистрация: 22.6.2003 Где: Казахстан, Астана Репутация: 17 Всего: 59 |
Ладно, все по порядку начиная со 2-ого пункта. 2. Не обязательно она должна быть. Это я привел из моего опыта создания сервера АСУДД, когда он должен был держать непрерывную связь с более чем 300 перекрестков (клиентов). И нужна была возможность отправки одного сообщения сразу всем клиентам. Тогда без коллекции (которая в принципе была SocketManager), не обойтись. При этом все соединения были актуальными и SocketManager сам занимался дисконект/конектами, приемкой/отправкой/обработкой сообщений так, что никакой другой объект его использующий не знал ничего. 3. Коллекция (тогда я писал на 1.1 фраймуорке) была простым синхронизированным ArrayList:
Это давало мне возможность не задумываться о том, что и с какого потока вызывалось и как менялась коллекция. Правда foreach итерация должна быть тоже синхронизированной:
До тех пор пока выполняется вышенаписанный цикл (независимо в каком потоке), все остальные потоки не смогут ничего сделать с этой коллекций, а значит это будет безопасно для foreach 4. Например так: bool isDisconnect = Socket.Poll(1, SelectMode.SelectRead); 5. Нету, и наверное не появится. 6. Точно не помню, но помоему вызывается System.ObjectDisposedException
На всякий случай посмотри какой тип объекта Exception вызывается и замени на соответствующий. Если я не ошибся, то помни, что это исключение может вызвать не только Socket, но и любой другой Disposed объект, если ты к нему обратишься в этом try/catch блоке. Но на своей практика я никогда не отлавливал закрытие таким образом, просто все проверял заранее, и никаких исключений не вываливалось
имя метода, который обрабатывает то самое событие, о котором я писал в топике. -------------------- Если тебе плюют в спину, значит ты впереди... |
||||||||
|
|||||||||
| zss |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 708 Регистрация: 17.6.2004 Репутация: нет Всего: 2 |
-Mikle-, спасибо за подробный ответ. Посмотрел MSDN - вроде должет вывалить ObjectDisposedException.
Вопрос чисто теоретический. В С++ есть такая хрень для сокетов Беркли как keep_alive. 1. Кто должет опрашивать - клиент или сервер ? 2. Если сервер, то вопрос снимается, т.к. под С# у меня только клиент, а на сервере это реализовано. А если клиент, то как в C# реализовать опрос сервера если нет обмена. З.Ы. Вопрос возник из-за того, что на GPRS соединении КПК и сервера, если нет обмена данных, то приходит сообщение о том, что сокет разорвал соединение. Не могу понят кто его рвет - клиент или сервер. У меня опрашивает сервер. Может быть С# клиент просто не отвечает и ему нужно об этом как-то сказать ? |
|||
|
||||
| mr.DUDA |
|
|||
|
3D-маньяк ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 8244 Регистрация: 27.7.2003 Где: город-герой Минск Репутация: 110 Всего: 232 |
zss,
Модератор: Пожалуйста, один топик - один вопрос. -------------------- ![]() |
|||
|
||||
![]()
|
| Прежде чем создать тему, посмотрите сюда: | |
|
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |