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

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

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

} 

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

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

Ответы [ 5 ]

4 голосов
/ 08 января 2010

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

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

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

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

2 голосов
/ 08 января 2010

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

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

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

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

2 голосов
/ 08 января 2010

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

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

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

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

2 голосов
/ 08 января 2010

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

1 голос
/ 08 января 2010

Есть два способа решения этой проблемы:

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

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

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

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

NextMethod(FirstMethod());

Чтобы заставить FirstMethod завершить работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...