Вызывается ли метод callBack до присваивания или после?

У меня есть приведенный ниже код, который в основном вызывает доменную службу в приложении SilverLight.

LoadOperation<tCity> loadOperation = _dataContext.Load(query,callBack, true);

Не подскажете, какую операцию делать первой?

Вызывается ли метод callBack до назначения переменной loadOperation или после ее назначения?

Спасибо


person pencilCake    schedule 07.10.2010    source источник


Ответы (3)


Предполагая, что это должна быть асинхронная операция, теоретически это может произойти в любом случае. Асинхронная операция должна выполняться в другом потоке, и если она завершается до возврата Load, обратный вызов может быть вызван до завершения присваивания.

На практике я ожидаю, что асинхронный вызов займет намного больше времени, чем любая уборка Load в конце метода, но я также не стал бы включать это предположение в код. Если нет явной синхронизации, гарантирующей, что присваивание произойдет до обратного вызова, я не думаю, что на нее стоит полагаться.

Даже если в данный момент присваивание всегда происходит первым, учтите:

  • Что произойдет, если в данный момент нет подключения к сети? Асинхронный вызов может очень быстро завершиться ошибкой.
  • Что произойдет, если кеширование будет добавлено на стороне клиента? Вызов может быть успешным очень быстро.
  • Я не знаю, какое тестирование вы можете проводить против служб RIA, но иногда вам может понадобиться имитировать асинхронные вызовы, заставляя их выполнять обратный вызов в том же потоке, что означает обратный вызов может произойти в тестах перед заданием. Этого можно было бы избежать, запустив по-настоящему асинхронный фиктивный вызов, но обработка многопоточности в тестах может стать сложной задачей; иногда проще всего сделать все синхронно.

РЕДАКТИРОВАТЬ: я думал об этом больше и пытался выяснить причины, по которым я интуитивно чувствую, что вы не должны делать это предположение, хотя в реальности это почти всегда будет хорошо.

Опираться на порядок операций противоречит духу асинхронности.

Вы должны (IMO) что-то запускать и быть готовым к тому, что это вернется в любое время. Вот как вы должны думать об этом. Как только вы начнете спускаться по скользкой дорожке «Я уверен, что смогу выполнить небольшую работу, прежде чем будет получен ответ», вы окажетесь в мире неопределенности.

person Jon Skeet    schedule 07.10.2010
comment
@HiTech: Я согласен, что на самом деле это произойдет до того, как Load вернется, но действительно ли это гарантировано - или это просто потому, что на практике вызов занимает некоторое время? Другими словами, вы говорите, что есть синхронизация, чтобы гарантировать, что обратный вызов не произойдет до возврата Load? Я отредактирую свой ответ. - person Jon Skeet; 07.10.2010
comment
@HiTech: Но вы все еще говорите, что это просто потому, что это происходит быстрее, а не из-за синхронизации, верно? Это похоже на состояние гонки, но эта гонка — это гонка на 100 миль между черепахой и поездом? Если это так, то наиболее подходящий подход, безусловно, зависит от мнения, но я думаю, что разумно защищать код по причинам, указанным в моем отредактированном ответе. - person Jon Skeet; 07.10.2010
comment
+1 для Джона здесь. Я согласен, что асинхронный вызов займет гораздо больше времени, но это не гарантировано в любом случае, и в этом главное дело. Код, основанный на подобных предположениях, может быть головной болью при изменении и сопровождении, потому что предположения определяются в уме, а не в коде. Если вы действительно уверены, что этот метод еще не был вызван, и вы хотите положиться на него, выполните Assert. Это даст подсказку всем, кто будет работать с вашим кодом позже, на какие условия опирается ваш код. - person Dan Abramov; 07.10.2010
comment
@HiTech: Зачем ему выполнять какую-либо блокировку? Если вы относитесь к асинхронным вызовам так, как будто это может произойти в любое время, вам не нужна синхронизация. Я просто говорю, что глупо кодировать предположение, что асинхронный вызов произойдет в определенное время, если нет гарантий, что этого не произойдет. Обратите внимание, что просмотр в рефлекторе покажет вам только текущую реализацию. Есть ли гарантии, написанные в документах? Если нет, то не делайте никаких предположений. - person Jon Skeet; 07.10.2010
comment
@HiTech: Да, я думаю, что лучше всего будет согласиться с несогласием. Лично я не думаю, что кодирование, защищающее от условий гонки, неуместно, но поехали. - person Jon Skeet; 07.10.2010
comment
@HiTech: Вы читали последнее редактирование моего ответа? Это должно немного объяснить мои мысли. Если вы используете асинхронные операции, вы должны думать о них как о действительно асинхронных, IMO. - person Jon Skeet; 08.10.2010
comment
@HiTech: Разве ты сам только что не ответил на него? Обратный вызов должен использовать контекст, а не возвращаемое значение... так зачем вам писать, что предполагает, что присваивание имело место? - person Jon Skeet; 08.10.2010
comment
@HiTech: Мой ответ основан на общей асинхронной практике - он вообще не специфичен для C#. Если вы делаете асинхронный запрос, вы должны думать о нем как о полностью отдельном от потока, который его запустил, если нет явной синхронизации (например, чтобы сделать обратный вызов в потоке диспетчера). Если OP хочет использовать результат назначения, это, вероятно, указывает на то, что они неправильно думают об асинхронных вызовах. Я думаю, что это стоит отметить лично. - person Jon Skeet; 08.10.2010
comment
@HiTech: я бы сказал, что на самом деле я сосредотачиваюсь на большей картине, а не на мелочах. Что касается того, верен ли ваш ответ: на практике я так считаю. Теоретически нет. Вы по-прежнему поощряете людей полагаться на последовательность, которая не гарантируется и не должна быть гарантирована из-за асинхронной природы системы. Добавлю комментарий. - person Jon Skeet; 08.10.2010
comment
@HiTech: Пожалуйста, не удаляйте свои комментарии - это бессмысленно и просто удаляет полезную беседу, которую другие люди могут прочитать позже. (Я вообще не верю аргументу экономии пропускной способности.) - person Jon Skeet; 08.10.2010
comment
@HiTech: Честно говоря, мне такое поведение кажется хладнокровным. Для кого-то совершенно легко прочитать только ответы, если они действительно этого хотят. Они написаны более крупным шрифтом и все такое. Учитывая, что некоторые комментарии были одобрены, очевидно, что другие люди находят дискуссию интересной. Почему вы хотите, чтобы будущие читатели не сочли это обсуждение интересным? - person Jon Skeet; 08.10.2010

Во-первых, я бы сказал, напишите свой обратный вызов без каких-либо предположений. Но помимо этого я не понимаю, как обратный вызов мог произойти до присваивания. Операция загрузки должна была бы вернуться сразу после вращения потока.

person Kirk    schedule 10.10.2010

Есть 3 возможных ответа на этот очень специфический вопрос RIA Services:

  1. Он возвращает присваивание перед обратным вызовом.
  2. Обратный вызов может произойти до присваивания.
  3. Тебе все равно.

Случай 1: На основании исследования .Net Reflector фактического рассматриваемого метода загрузки оказалось, что он не может вызвать обратный вызов до того, как произойдет возврат. (Если кто-то хочет возразить, мы приглашаем вас объяснить тонкости запуска фоновых потоков).

Случай 2: Доказательство того, что "небо падает" возможно, должно быть показано в отраженном коде. (Если кто-то хочет поддержать это, он также может объяснить тонкости запуска фоновых потоков).

Случай 3. В действительности возвращаемое значение метода загрузки служб RIA обычно используется для назначения источника данных отложенной загрузки. Он не используется обратным вызовом. Обратному вызову передается собственный контекст загруженных данных в качестве параметра.

StackOverflow посвящен практическим ответам на код, поэтому единственным практичным ответом является вариант 3:

Вам все равно, (поскольку вы не должны использовать значение присваивания из обратного вызова).

person Gone Coding    schedule 14.10.2010