Когда нужно заботиться о завершении одного метода, прежде чем начать следующий?

2

Используя С# в WPF вместе с LINQ to SQL и LINQ для запроса моих общих коллекций, я заметил, что иногда, когда я использую несколько методов один за другим, а результаты первого необходимы для следующей функции, я должен заботиться о завершающие действия первой функции перед следующим.

SomeMethod()
{
  FirstMethod();
  NextMethod();
  ....

} 

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

Можно ли суммировать, когда возможность "еще не обновлена ​​для продолжения" может произойти в С# и как эта проблема в целом решена?

  • 1
    Я действительно не понимаю, что вы имеете в виду. Что вы имеете в виду, используя метод последовательно? Последовательная? Что вы подразумеваете под "еще не обновлен для продолжения"?
  • 0
    Извините за мой английский, это не мой родной язык. Под «следовательно» я имел в виду «один за другим» и «быть связанным».
Показать ещё 1 комментарий
Теги:
linq
synchronization

5 ответов

4
Лучший ответ

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

(Например, вы можете начать использовать DataReader, он вернет управление вашему коду, прежде чем он будет иметь все данные, но он по-прежнему защищает вас от "опережения", t дает вам ложный "конец".Если вы используете его быстрее, чем получает данные, это заставит вашу следующую команду ждать, а не испортить вашу логику. И если вы определили выражение Linq на самом деле пока не выполняется, он всегда будет со временем, когда вы попросите его результаты.)

.Net очень хорошо защищает вас от асинхронных проблем, если вы не попросите их. Если вы многопоточность или запускаете внешний процесс (веб-сервис или что-то еще) где-то в другом месте, а затем сразу же предполагаете, что он завершен, и вы можете зависеть от его результата, то у вас будут проблемы. Но в общем, просто код прочь.

Иногда мне было сложно справиться с асинхронными проблемами, но они никогда меня не удивили.

2

Обычно NextMethod() будет выполняться сразу после возврата FirstMethod().

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

В этом случае методы действительно будут выполняться почти одновременно.

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

2

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

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

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

Для детерминизма думать о охранных высказываниях в функции. Если моя функция должна иметь строку и не нулевой объект, я сначала проверяю эти условия, когда мы вводим функцию, прежде чем я начну вызывать методы на этих объектах (вызов string.ToLower() в порядке, но плохой на нуле объект). Таким образом, я делаю детерминизм во время выполнения, чтобы предотвратить ошибки в моем коде (например, NullReference и т.д.). Компилятор выполняет свой собственный детерминизм времени компиляции, но не может знать состояние объектов во время выполнения, поэтому он выполняет только его сравнения по операциям (независимо от того, являются ли они семантически действительными или нет).

2

Это должно быть проблемой, только если функция, которую вы вызываете, является асинхронной или "неблокирующей", что является необычным. Просто проверьте документацию функции. Если вы явно используете поток или потоки, используйте соединение, чтобы обеспечить завершение выполнения. Если вы используете функцию, имя которой начинается с "Начать", вызовите следующую операцию из соответствующего Конец. Последнее средство использует цикл и Thread.Sleep(0); чтобы заставить выполнение ждать определенного условия, чтобы быть истинным.

1

Существует два способа решения этого вопроса:

Используйте механизм блокировки или перепроектируйте свои методы для комбинирования друг с другом, заставляя их выполнить сначала.

Механизм блокировки может либо блокировать поток до завершения рабочего процесса, либо с помощью логического значения с циклом while:

while (locked)
{
    // sleep or do something else
}
... rest of code

Рефакторинг вашего кода будет включать передачу значения одного метода в другой метод:

NextMethod(FirstMethod());

Чтобы заставить FirstMethod закончить.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню