Вы хотите проверить Экспресс-обработка ошибок . Оттуда:
app.param('userId', function(req, res, next, id) {
User.get(id, function(err, user) {
if (err) return next(err);
if (!user) return next(new Error('failed to find user'));
req.user = user;
next();
});
});
Сладость, которую вам не хватает, это return
next(...)
Нет, ваш объект не будет обработан сборщиком мусора, пока не завершится обратный вызов. Согласно сборщик мусора уничтожает временно не упоминаемые объекты во время асинхронных вызовов в .NET? , « асинхронный API сохраняет ссылку на ваш запрос (в пуле потоков, где размещаются асинхронные операции ввода-вывода) и так что он не будет собираться мусором, пока не завершится. "
Но ваш код также делает то, в чем он не нуждается: вам не нужно отсоединять обработчик событий и не нужно вызовите Dispose в веб-клиенте. (Dispose () фактически не реализуется WebClient - вы можете увидеть это в справочном источнике .NET Framework по адресу http://referencesource.microsoft.com/netframework.aspx ).
Так ты не делаешь? На самом деле нужно ссылаться на экземпляр веб-клиента в вашем обратном вызове. Другими словами, следующий код будет работать так же хорошо и позволит избежать любых потенциальных проблем (обсуждаемых выше) обращения к внешним локальным переменным изнутри делегата.
private void DownloadData(Uri uri)
{
WebClient webClient = new WebClient();
DownloadDataCompletedEventHandler eh = null;
eh = delegate(object sender, DownloadDataCompletedEventArgs e)
{
OnDataDownloaded();
};
webClient.DownloadDataCompleted += eh;
webClient.DownloadDataAsync(uri);
}
В любом случае, вы, вероятно, захотите поискать источник вашей ошибки в другом месте. Одно из мест, где я бы посмотрел, - это результаты HTTP-вызовов: у вас может быть нехватка памяти, могут быть ошибки сервера и т. Д. Вы можете посмотреть e.Error, чтобы узнать, действительно ли работают вызовы.
d посмотрите на результаты HTTP-вызовов - у вас может быть нехватка памяти, могут возникать ошибки сервера и т. д. Вы можете посмотреть e.Error, чтобы узнать, действительно ли работают вызовы. d посмотрите на результаты HTTP-вызовов - у вас может быть нехватка памяти, могут возникать ошибки сервера и т. д. Вы можете посмотреть e.Error, чтобы узнать, действительно ли работают вызовы.repaint () на самом деле не перерисовывает, а просто запрашивает перерисовку компонента.
поэтому, пока имеется ссылка на сам делегат, WebClient
не может быть. Мое обоснованное предположение состоит в том, что некоторая часть системы где-то должна удерживать обратный вызов, чтобы знать, что делать при поступлении сетевого трафика, и этот обратный вызов в конечном итоге (косвенно) приведет к вашему делегату, так что все в порядке . Вы можете попробовать отладить приложение с помощью инструментов отладки для Windows - они позволяют увидеть, что именно хранит ссылки на конкретный объект ( с соответствующим плагином ) . Очень полезно для таких случаев.
Однако я не знаю ответа на ваш вопрос. Одна из возможностей состоит в том, что на время операции WebClient делает себя одним из «корневых» объектов, которые никогда не собираются сборщиком мусора (приложение .NET обычно имеет от 5 до 10 таких объектов, которые являются корнями нескольких используемых ссылочных деревьев. приложением). Однако это чистое предположение.
При создании анонимного метода со ссылкой на переменную области видимости (webClient в вашем случае) и создайте собственную переменную со ссылкой на этот объект. Итак, как предполагает Джон, ваш делегат будет содержать ссылку на webClient, и до того, как делегат отменит регистрацию, webClient не может быть собран с помощью сборщика мусора.
Однако я обычно предлагаю не использовать ссылку webClient в вашем методе делегата, но чтобы привести отправителя к внутренней переменной.
Оборотная сторона монеты ... если вы где-то сохранили ссылку на WebClient
, просто чтобы посмотреть, имеет ли это значение ... устраняет ли это проблему совсем прочь? Может быть, проще проверить это и быть уверенным, чем угадывать то, что кажется логичным.