Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> обработчик исключений 
:(
    Опции темы
mr.DUDA
Дата 22.1.2007, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Цитата(zss @  22.1.2007,  20:25 Найти цитируемый пост)
Если в потоке произойдет исключение в методе write или read, то будет вызвано событие OnMethodв котором я пытаюсь остановить поток. Вопрос: дождусь ли я его ?

Смотри: есть метод, внутри которого предполагается наличие исключительных ситуаций. Имя этому методу write/read. Для того, чтобы обработать эти ситуации, метод который вызывает write/read, заключает вызовы этих методов в try...catch - и всё пучком... Пока мы не начинаем говорить о многопоточности. В этом случае, тот метод который реализует поток (MainThread), собственно и должен обработать исключение (делай "раз!") и сгенерировать событие (делай "два!"), если он предполагает подписчика на это событие. В данном случае, событие - это прикладная логика, предусматривающая внешний код, который реагирует на наличие исключительных ситуаций. Так или иначе, в любом случае обрабатывать исключения должен тот код, который:

- а) сам генерирует исключения
- б) вызывает код, генерирующий исключения

В том и другом случае, речь всегда идёт об одном потоке. Ответственность за обработку исключений всегда берёт на себя тот, кто вызывает потенциально опасный код. То есть - это либо участок метода, заключенный в try..catch, либо мелкий кусок кода, заключенный в try..catch и вызывающий другой метод.


--------------------
user posted image
PM MAIL WWW   Вверх
-Mikle-
Дата 22.1.2007, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Цитата(zss @  23.1.2007,  00:25 Найти цитируемый пост)
Вопрос: дождусь ли я его ?

Если само событие ты вызываешь из метода write() или read(), то метод обработки события будет вызываться в том же потоке, что и write/read. Метод m_thread.Join() без параметров, бесконечно ждет завершения потока, а в данном случае он никогда не дождется, так как вызывается из того же потока завершение которого он ждет (надеюсь понятно smile )

Добавлено @ 22:11 
Цитата(zss @  20.1.2007,  20:11 Найти цитируемый пост)
Я ловлю SocketException. Я хочу в методах при любой ошибке возвращать статус завершения,
а лишь только если сокет закрылся или обрыв - тогда дергать метод в котором отработает нужный код.

поясни подробней немного, наверняка нужен просто другой подход


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
zss
Дата 22.1.2007, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



блин... чтож дак все сложно.

Ладно - я все понял. Обработка должна быть при вызове методов, которые могут бросить исключение.
Я тогда зайду с другой стороны. Как можно убить объект (или сказать его владельцу). Что его уже буссмысленно использовать
и нужно создавать заново.

Например если сокет закрылся, то класс, использующий его, использовать бесполезно.
При этом нужно что-то сделать извне и заставить заново его создать.
PM MAIL ICQ   Вверх
-Mikle-
Дата 22.1.2007, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Цитата(zss @  23.1.2007,  01:14 Найти цитируемый пост)
Например если сокет закрылся, то класс, использующий его, использовать бесполезно.
При этом нужно что-то сделать извне и заставить заново его создать.


Типичная ситуация. Я всегда делал так:

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() можно перед отправкой или получением данных из сокета.

(Вроде-бы я ничего не упустил smile )

Добавлено @ 22:42 
И вообще, помоему, тема уже переросла в другой раздел


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
ivashkanet
Дата 23.1.2007, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(zss @  22.1.2007,  20:25 Найти цитируемый пост)
Вопрос: дождусь ли я его ?

Срочно читать про события и мультикаст делегаты  smile 
Вызывая MyEvent(this, e) ты всего лишь по очереди вызываешь методы, зарегистрированные в мультикаст делегате, с одними и теме же параметрами. А так как  выполнение инструкций самого метода выполняет поток его вызвавший, то эти методы будут выполняться в том же потоке.

В Multicast delegat (делегат на метод возвращающий void) можно регистрировать много методов (объединять их в одну связку). После чего, при вызове делегата, будут вызваны все методы, которые были зарегестрированы (объеденены) в делегате.

Евент от делегата отличается только тем, что имеет более удобный способ регистрации методов:
Код

MyEvent+= MySub;
// вместо
MyMulticastDelegate = (MyMulticastDelegate)Delegate.Combine(myMulticastDelegate, new MyMulticastDelegate(MySub))

Может где-то я здесь наврал, но суть верна

Пример:
Код

    class Program
    {
        delegate void MyMulticastDelegate();
        [STAThread]
        static void Main(string[] args)
        {
            MyMulticastDelegate myMulticastDelegate = new MyMulticastDelegate(MySub);

            Console.WriteLine("Test 1:");
            myMulticastDelegate();


            // Комбинирование делегатов
            myMulticastDelegate = (MyMulticastDelegate)Delegate.Combine(myMulticastDelegate, new MyMulticastDelegate(MySub1));

            Console.WriteLine();
            Console.WriteLine("Test 2:");
            // вызов (выполнение) всех зарегистрированных делегатов
            myMulticastDelegate();

            Console.ReadKey();
        }

        static void MySub()
        {
            Console.WriteLine("MySub was called");
        }
        static void MySub1()
        {
            Console.WriteLine("MySub1 was called");
        }
    }

PM MAIL WWW ICQ   Вверх
zss
Дата 23.1.2007, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



-Mikle-, интересная идея. Тоесть я создаю mySock и подписываюсь у него на событие OnDisconnect.

1. Это схоже с тем, что я впринципе хотел smile
2. Зачем тогда коллекция ? Достаточно создать класс и самому отслеживать время его жизни. (как правило редко
нужно несколько сокетов)
3. Что будет если это событие вызвано из другого потока (про что я и говорил выше - или коллекция это может решить ?)
4. Как пингонуть сокет ?
5 Может у Socket уже есть событие на закрытие ?
6 Какой код ошибки позволит узнать, что исключение было вызванно именно из-за закрытия сокета ?

Добавлено @ 09:28 
Цитата(-Mikle- @  22.1.2007,  22:38 Найти цитируемый пост)
На этом событие висит метод OnDisconnectHandler(...) в mySockColl

и что это такое ?

Это сообщение отредактировал(а) zss - 23.1.2007, 09:56
PM MAIL ICQ   Вверх
zss
Дата 23.1.2007, 10:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



Цитата(ivashkanet @  23.1.2007,  09:11 Найти цитируемый пост)
Вызывая MyEvent(this, e) ты всего лишь по очереди вызываешь методы, зарегистрированные в мультикаст делегате, с одними и теме же параметрами. А так как  выполнение инструкций самого метода выполняет поток его вызвавший, то эти методы будут выполняться в том же потоке.

а если через делегат вызвать AbortThread ?
PM MAIL ICQ   Вверх
-Mikle-
Дата 24.1.2007, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 17
Всего: 59



Цитата(zss @  23.1.2007,  12:27 Найти цитируемый пост)

1. Это схоже с тем, что я впринципе хотел 
2. Зачем тогда коллекция ? Достаточно создать класс и самому отслеживать время его жизни. (как правило редко
нужно несколько сокетов)
3. Что будет если это событие вызвано из другого потока (про что я и говорил выше - или коллекция это может решить ?)
4. Как пингонуть сокет ?
5 Может у Socket уже есть событие на закрытие ?
6 Какой код ошибки позволит узнать, что исключение было вызванно именно из-за закрытия сокета ?


Ладно, все по порядку начиная со 2-ого пункта.

2. Не обязательно она должна быть. Это я привел из моего опыта создания сервера АСУДД, когда он должен был держать непрерывную связь с более чем 300 перекрестков (клиентов). И нужна была возможность отправки одного сообщения сразу всем клиентам. Тогда без коллекции (которая в принципе была SocketManager), не обойтись. При этом все соединения были актуальными и SocketManager сам занимался дисконект/конектами, приемкой/отправкой/обработкой сообщений так, что никакой другой объект его использующий не знал ничего.

3. Коллекция (тогда я писал на 1.1 фраймуорке) была простым синхронизированным ArrayList:
Код

ArrayList clientList = ArrayList.Synchronized( new ArrayList() );

Это давало мне возможность не задумываться о том, что и с какого потока вызывалось и как менялась коллекция. Правда foreach итерация должна быть тоже синхронизированной:
Код

            lock( clientList.SyncRoot )
            {
                foreach(mySock sp in clientList )
                {
                    // тело итератора foreach
                }
            }

До тех пор пока выполняется вышенаписанный цикл (независимо в каком потоке), все остальные потоки не смогут ничего сделать с этой коллекций, а значит это будет безопасно для foreach

4. Например так:
bool isDisconnect = Socket.Poll(1, SelectMode.SelectRead);

5. Нету, и наверное не появится.

6. Точно не помню, но помоему вызывается System.ObjectDisposedException
Код

private void SendData(...........)
{
    try
    {
        Socket.Send(.....);
    }
    catch(ObjectDisposedException ex)
    {
        // Socket закрытый
    }
    catch(Exception ex)
    {
        // Другая ошибка
    }
    finally
    {
        // Сделаем что-то в любом случае перед выходом из процедуры
    }
}

На всякий случай посмотри какой тип объекта Exception вызывается и замени на соответствующий. Если я не ошибся, то помни, что это исключение может вызвать не только Socket, но и любой другой Disposed объект, если ты к нему обратишься в этом try/catch блоке. Но на своей практика я никогда не отлавливал закрытие таким образом, просто все проверял заранее, и никаких исключений не вываливалось smile

Цитата(zss @  23.1.2007,  12:27 Найти цитируемый пост)
Добавлено @ 12:28 

Цитата(-Mikle- @  22.1.2007,  22:38 )
На этом событие висит метод OnDisconnectHandler(...) в mySockColl


и что это такое ?

имя метода, который обрабатывает то самое событие, о котором я писал в топике.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
zss
Дата 24.1.2007, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 708
Регистрация: 17.6.2004

Репутация: нет
Всего: 2



-Mikle-, спасибо за подробный ответ. Посмотрел MSDN - вроде должет вывалить ObjectDisposedException.

Вопрос чисто теоретический. В С++ есть такая хрень для сокетов Беркли как keep_alive.

1. Кто должет опрашивать - клиент или сервер ?
2. Если сервер, то вопрос снимается, т.к. под С# у меня только клиент, а на сервере это реализовано. 
А если клиент, то как в C# реализовать опрос сервера если нет обмена.

З.Ы. Вопрос возник из-за того, что на GPRS соединении КПК и сервера, если нет обмена данных, то приходит сообщение о том,
что сокет разорвал соединение. Не могу понят кто его рвет - клиент или сервер. У меня опрашивает сервер. Может быть 
С# клиент просто не отвечает и ему нужно об этом как-то сказать ?
PM MAIL ICQ   Вверх
mr.DUDA
Дата 25.1.2007, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



zss, 
Модератор: Пожалуйста, один топик - один вопрос.


--------------------
user posted image
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0560 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.