Здравствуйте, jedi, Вы писали:
J>Это все хорошо если обработка происходит в одном месте. В реальном же приложении, файл открывается и начинается обработка в отдельном потоке. закрыть файл там где его открывали не получится. Ровно то же самое с сокетом в моем изначальном примере.
У меня как-то получалось, наверное я что-то делал неправильно.
_FR>>А ловить OOM на любом new — это паранойя. Если есть метод, который, по спецификации такое может выбросить — ну что ж делать, но ожидать подлянки откуда угодно — глупо, повторю. J>Я и не предлагал его ловить при каждом new, а всего лишь там где в new передается объект, требующий вызов Dispose.
А в чём разница-то? Вам так же показали ситуацию, при которой вызов Dispose может быть прерван вызовом Thread.Abort(). Как из неё можно было бы выкрутиться и стоит ли вообще пытаться?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, jedi, Вы писали:
J>>Это все хорошо если обработка происходит в одном месте. В реальном же приложении, файл открывается и начинается обработка в отдельном потоке. закрыть файл там где его открывали не получится. Ровно то же самое с сокетом в моем изначальном примере.
_FR>У меня как-то получалось, наверное я что-то делал неправильно.
По-моему Вы просто не думали об этой ситуации. И, слава Богу, она не возникала. Я же предпочитаю подумать 1 раз и пользовать паттерном в следующий раз.
Например таким:
class Connection
{
private Connection(Socket socket)
{
// Perform initialization
}
static public Create(Socket socket)
{
try
{
return new Connection(socket);
}
catch
{
socket.Close();
throw;
}
}
}
Вот и все решение поднятой в начале проблемы. Я не понимаю из-за чего поднялся такой вой
_FR>А в чём разница-то? Вам так же показали ситуацию, при которой вызов Dispose может быть прерван вызовом Thread.Abort(). Как из неё можно было бы выкрутиться и стоит ли вообще пытаться?
Этой ситуации просто не может быть. За мои 10 лет кодирования, я ни разу не применял ни TerminateThread(), ни Thread.Abort() и надеюсь сохранить достаточную трезвость ума, чтоб не применять их и в будущем . Все мои серверные приложения жили (некоторые живут до сих пор) счастливо. Наверное я что-то делал неправильно (с).
Здравствуйте, samius, Вы писали:
J>>Вот и все решение поднятой в начале проблемы. Я не понимаю из-за чего поднялся такой вой
S>А потом после создания экземпляра Connection возникло InvalidOperationException при чтени данных, и ровно такой же катч придется писать и там?
Он там и так есть, если вы вызываете BeginSend или BeginReceive — это ваша святая обязанность поймать любое неожиданное исключение в обработчике завершения асинхронной операции, залогировать его и закрыть соединение. Иначе будет плохо.
S>Что-то не тянет это на паттерн.
Здравствуйте, jedi, Вы писали:
J>Здравствуйте, samius, Вы писали:
J>>>Вот и все решение поднятой в начале проблемы. Я не понимаю из-за чего поднялся такой вой
S>>А потом после создания экземпляра Connection возникло InvalidOperationException при чтени данных, и ровно такой же катч придется писать и там?
J>Он там и так есть, если вы вызываете BeginSend или BeginReceive — это ваша святая обязанность поймать любое неожиданное исключение в обработчике завершения асинхронной операции, залогировать его и закрыть соединение. Иначе будет плохо.
Именно там это и надо делать, а не в Connection.Create!
Здравствуйте, samius, Вы писали:
S>Здравствуйте, jedi, Вы писали:
J>>Здравствуйте, samius, Вы писали:
J>>>>Вот и все решение поднятой в начале проблемы. Я не понимаю из-за чего поднялся такой вой
S>>>А потом после создания экземпляра Connection возникло InvalidOperationException при чтени данных, и ровно такой же катч придется писать и там?
J>>Он там и так есть, если вы вызываете BeginSend или BeginReceive — это ваша святая обязанность поймать любое неожиданное исключение в обработчике завершения асинхронной операции, залогировать его и закрыть соединение. Иначе будет плохо.
S>Именно там это и надо делать, а не в Connection.Create!
Наша песня хороша начинай сначала ...
Еще раз, до обработчка завершения BeginSend/BeginReceive дело может не дойти если код "new Connection" вызвал OutOfMemoryException.
Здравствуйте, jedi, Вы писали:
J>>>Он там и так есть, если вы вызываете BeginSend или BeginReceive — это ваша святая обязанность поймать любое неожиданное исключение в обработчике завершения асинхронной операции, залогировать его и закрыть соединение. Иначе будет плохо.
S>>Именно там это и надо делать, а не в Connection.Create!
J>Наша песня хороша начинай сначала ... J>Еще раз, до обработчка завершения BeginSend/BeginReceive дело может не дойти если код "new Connection" вызвал OutOfMemoryException.
Не возникало мысли, что до new Connection дело тоже может не дойти?
Потому код, вызывающий _listener.EndAccept(ar) уже должен быть в блоке try/catch раз на то пошло. Только вот экземпляра сокета catch он не увидит, если пробросило в EndAccept, потому закрытие сокета будет висеть на GC.
Здравствуйте, samius, Вы писали:
S>Не возникало мысли, что до new Connection дело тоже может не дойти?
S>Потому код, вызывающий _listener.EndAccept(ar) уже должен быть в блоке try/catch раз на то пошло.
С чего ты решил что это код не в try/catch?
S>Только вот экземпляра сокета catch он не увидит, если пробросило в EndAccept, потому закрытие сокета будет висеть на GC.
Если EndAccept написал так, что бросает исключение не зыкрыв висящий сокет — это очень плохо и минус парням из майкрософт.
Если же до реального вызова accept() в коде EndAccept() не дошло, то сокет останется в ядре либо до следующего вызова accept(),
либо будет закрыт по истечении некоторого таймаута, что меня вполне устраивает. В отличие от ситуации, когда он будет висеть
неопределенно долго до сборки мусора в первом поколении.
Здравствуйте, jedi, Вы писали:
J>Здравствуйте, samius, Вы писали:
S>>Не возникало мысли, что до new Connection дело тоже может не дойти?
S>>Потому код, вызывающий _listener.EndAccept(ar) уже должен быть в блоке try/catch раз на то пошло.
J>С чего ты решил что это код не в try/catch?
С того, что твой паттерн заворачивает конструктор Connection в отдельный try/catch.
S>>Только вот экземпляра сокета catch он не увидит, если пробросило в EndAccept, потому закрытие сокета будет висеть на GC.
J>Если EndAccept написал так, что бросает исключение не зыкрыв висящий сокет — это очень плохо и минус парням из майкрософт.
Сам писал, что речь не только о сокете, что это может быть все что угодно.
J>Если же до реального вызова accept() в коде EndAccept() не дошло, то сокет останется в ядре либо до следующего вызова accept(), J>либо будет закрыт по истечении некоторого таймаута, что меня вполне устраивает. В отличие от ситуации, когда он будет висеть
Кто сказал, что этот таймаут случится раньше чем сборка в первом поколении?
J>неопределенно долго до сборки мусора в первом поколении.
Откуда уверенность про первое поколение? Может этот сокет уже пережил не одну сборку?
Здравствуйте, samius, Вы писали:
J>>С чего ты решил что это код не в try/catch?
S>С того, что твой паттерн заворачивает конструктор Connection в отдельный try/catch.
Я не вижу как одно мешает другому
S>>>Только вот экземпляра сокета catch он не увидит, если пробросило в EndAccept, потому закрытие сокета будет висеть на GC.
J>>Если EndAccept написал так, что бросает исключение не зыкрыв висящий сокет — это очень плохо и минус парням из майкрософт. S>Сам писал, что речь не только о сокете, что это может быть все что угодно.
Я не вижу здесь противоречия. Покажи.
J>>Если же до реального вызова accept() в коде EndAccept() не дошло, то сокет останется в ядре либо до следующего вызова accept(), J>>либо будет закрыт по истечении некоторого таймаута, что меня вполне устраивает. В отличие от ситуации, когда он будет висеть S>Кто сказал, что этот таймаут случится раньше чем сборка в первом поколении?
Таймаут — это нечто определенное, даже если он большой. Сборка мусора — нет.
J>>неопределенно долго до сборки мусора в первом поколении. S>Откуда уверенность про первое поколение? Может этот сокет уже пережил не одну сборку?
Может. Уверенности нет. Просто объекты с финализатором (коим является SafeHandle сидящий внутри сокета) в нулевом поколении не собираются.
Здравствуйте, jedi, Вы писали:
J>Здравствуйте, samius, Вы писали:
J>>>С чего ты решил что это код не в try/catch?
S>>С того, что твой паттерн заворачивает конструктор Connection в отдельный try/catch.
J>Я не вижу как одно мешает другому
Мешать не мешает, но и смысла для заворачивания конструктора класса в отдельный try/catch тоже нет.
J>>>Если EndAccept написал так, что бросает исключение не зыкрыв висящий сокет — это очень плохо и минус парням из майкрософт. S>>Сам писал, что речь не только о сокете, что это может быть все что угодно.
J>Я не вижу здесь противоречия. Покажи.
Показать код, который не чистит ресурсы в случае исключения, будь то сокет, файл или транзакция?
Даже пробовать не буду.
MC>Может, но исключения OutOfMemoryException, StackOverflowException и ExecutionEngineException не отлавливаются вообще никак, и в этом случае происходит неизбежное закрытие программы.
Из приведенных только StackOverflowException обладает подобной особенностью по докам.
Вообще же
Исключения SEH всегда доставлялись средой CLR управляемому коду, используя ту же механику, что и для исключений, возникающих в самой программе.
К слову, в версии, 4.0 нас ждет интересная особенность
В версии 4 среды CLR группа разработчиков продукта делает исключения, указывающие на повреждение состояния процесса, отличными от всех прочих исключений. Мы выделили около десяти исключений SEH, которые будут указывать на повреждение состояния процесса. Их обозначения относятся к контексту, в котором создается исключение, а не к самому типу исключения. Это значит, что нарушения прав доступа, полученные от Windows, будут помечены как исключения CSE (исключения поврежденного состояния), а исключения, возникающие в коде пользователя в результате порождения нового System.AccessViolationException, не будут помечены как CSE
...
Начиная с версии 4 система исключений среды CLR не будет доставлять исключения CSE управляемому коду, если код не укажет явно, что он может обрабатывать исключения поврежденного состояния процесса. Это означает, что оператору catch (Exception e) в управляемом коде CSE передаваться не будут.
Здравствуйте, Arboz, Вы писали:
MC>>Может, но исключения OutOfMemoryException, StackOverflowException и ExecutionEngineException не отлавливаются вообще никак, и в этом случае происходит неизбежное закрытие программы.
A>Из приведенных только StackOverflowException обладает подобной особенностью по докам.
Да... ибо не ввести в заблуждение: OutOfMemoryException, StackOverflowException не CSE-исключения Источник
A set of exceptions indicate your process state is corrupted
а. Access Violations are the most common
b. Does not include Out of Memory, Division by Zero, Stack Overflow, Null Reference
Здравствуйте, Arboz, Вы писали:
A>Здравствуйте, Arboz, Вы писали:
A>Да... ибо не ввести в заблуждение: OutOfMemoryException, StackOverflowException не CSE-исключения A>Источник
Нет ли этой доки в человеческом формате? Ибо ставить новый офис нет ни желания, ни возможности. Заранее спасибо!
Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default.
Про другие два (упомянутые выше) исключения ничего подобного не сказано.
A>Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default.
A>Про другие два (упомянутые выше) исключения ничего подобного не сказано.