Такой вопрос. Есть некий класс, конструктор которого принимает в качестве параметра объект, реализующий интерфейс IDisposable.
Соответветвенно сам этот класс тоже реализует IDisposable.
class Connection : IDisposable
{
private Socket _socket;
public Connection(Socket socket)
{
// 1
_socket = socket;
// 2
}
public void Dispose()
{
// dispose stage 1
_socket.Close();
// dispose stage 2
}
}
class Foo
{
private void OnAccept(IAsyncResult ar)
{
socket = _listener.EndAccept(ar);
new Connection(socket);
}
}
Теперь вопрос. Что будет если случится исключение а) в точке 1; б) в точке 2.
Кто-то должен вызвать Close() сокету (иначе будет висеть у нас занятый порт до сборки мусора).
Такое:
private void OnAccept(IAsyncResult ar)
{
using (socket = _listener.EndAccept(ar))
{
new Connection(socket);
socket = null;
}
}
не прокатывает — warning CS0728: Possibly incorrect assignment to local 'conn' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.
Здравствуйте, jedi, Вы писали:
J>Спасибо, очень информативно. J>А если финалайзер вызвовется через год? Память может и не ресурс, а порты ТCP — вполне себе (странно, да?).
Если фрагмент кода в исходном сообщении это реальный код, а не иллюстрация, то думаю, что в точке №1 исключения не будет. С какой стати, какая там может произойти ошибка? Вы можете привести хоть один реальный пример исключения в точке №1?
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, jedi, Вы писали:
J>>Спасибо, очень информативно. J>>А если финалайзер вызвовется через год? Память может и не ресурс, а порты ТCP — вполне себе (странно, да?).
A>Если фрагмент кода в исходном сообщении это реальный код, а не иллюстрация, то думаю, что в точке №1 исключения не будет. С какой стати, какая там может произойти ошибка? Вы можете привести хоть один реальный пример исключения в точке №1?
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, jedi, Вы писали:
J>>Спасибо, очень информативно. J>>А если финалайзер вызвовется через год? Память может и не ресурс, а порты ТCP — вполне себе (странно, да?).
A>Если фрагмент кода в исходном сообщении это реальный код, а не иллюстрация, то думаю, что в точке №1 исключения не будет. С какой стати, какая там может произойти ошибка? Вы можете привести хоть один реальный пример исключения в точке №1?
Да что угодно. Поскольку это сервер к которому пишутся плагины. И ошибка в плагине не должна влиять на возможность других клиентов воспользоваться сервисом.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, jedi, Вы писали:
J>>Внимание, вопрос. Как это кошерно обработать?
L>Не вдаваясь в специфику: обычно рекомендуется чтобы временем жизни объекта управлял тот, кто его создает.
Я обеими руками за. Только вот не вижу как это применить в данной ситуации
Здравствуйте, jedi, Вы писали:
J>Да что угодно. Поскольку это сервер к которому пишутся плагины. И ошибка в плагине не должна влиять на возможность других клиентов воспользоваться сервисом.
Что угодно бывают разные. Сбой в оперативной памяти не та ошибочная ситуация, которую стоит обрабатывать.
Здравствуйте, jedi, Вы писали:
L>>Не вдаваясь в специфику: обычно рекомендуется чтобы временем жизни объекта управлял тот, кто его создает. J>Я обеими руками за. Только вот не вижу как это применить в данной ситуации
Как-как, не закрывать сокет. Пусть закрывает тот кто передает его в конструктор.
Здравствуйте, MozgC, Вы писали:
MC>Здравствуйте, jedi, Вы писали:
L>>>Не вдаваясь в специфику: обычно рекомендуется чтобы временем жизни объекта управлял тот, кто его создает. J>>Я обеими руками за. Только вот не вижу как это применить в данной ситуации
MC>Как-как, не закрывать сокет. Пусть закрывает тот кто передает его в конструктор.
У него недостаточно информации, чтобы решить когда это нужно делать.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, jedi, Вы писали:
J>>Да что угодно. Поскольку это сервер к которому пишутся плагины. И ошибка в плагине не должна влиять на возможность других клиентов воспользоваться сервисом.
A>Что угодно бывают разные. Сбой в оперативной памяти не та ошибочная ситуация, которую стоит обрабатывать.
При чем здесь сбой в оперативной памяти?
Банально — пытались записать в ивент лог, что принято новое соединения, произошло исключение — не хватило прав. Все, пусть сокет висит?
Я понимаю, что сборщик мусора все это когда-то вычистит. Но для 24/7 приложения это не годится.
И, да, я знаю что можно написать так:
Socket socket = null;
try
{
socket = _listener.EndAccept(ar);
new Connection(socket);
}
finally
{
if (socket != null)
socket.Close();
}
Я всего лишь спросил, как принято поступать в таких ситуациях. Вы же принялись убеждать, что все это фигня, думать об этом не нужно и сбрщик мусора когда-то почистит.
Здравствуйте, jedi, Вы писали:
J>У него недостаточно информации, чтобы решить когда это нужно делать.
Судя по вашему примеры вы вообще заморачиваетесь. Как сказал adontz — не должно быть никакого исключения в указанных вами точках, вы придумываете из разряда "а что если завтра на нас упадет ядерная бомба" — вероятности одинаковые. Хотя у варианта с ядерной бомбой вероятность и то наверное повыше
Здравствуйте, MozgC, Вы писали:
MC>Судя по вашему примеры вы вообще заморачиваетесь. Как сказал adontz — не должно быть никакого исключения в указанных вами точках, вы придумываете из разряда "а что если завтра на нас упадет ядерная бомба" — вероятности одинаковые. Хотя у варианта с ядерной бомбой вероятность и то наверное повыше
Здравствуйте, MozgC, Вы писали:
MC>Так чем-нибудь не устраивает?
Если вы почитаете ветку выше, я привел один-в-один такой же код.
В целом он меня устраивает. Я всего лишь пытался узнать есть ли какие-то штатные методы/паттерны для этой ситуации (я в .NET недавно).
MC>Но повторюсь, подумайте как можно сделать дизайн так, чтобы закрытием сокета занимался тот кто его создает.
Вы никогда не писали асинхронных серверов? Откуда коду принимающему соединения знать когда его нужно закрыть. Логика кода нелийнейная.
Здравствуйте, jedi, Вы писали:
J>Если вы почитаете ветку выше, я привел один-в-один такой же код. J>В целом он меня устраивает. Я всего лишь пытался узнать есть ли какие-то штатные методы/паттерны для этой ситуации (я в .NET недавно).
Нет, это не "один-в-один такой же код". В вашем случае такую конструкцию нужно будет писать в каждом месте создания объекта Connection. В моем варианте — нет.