2013-06-01 3 views
9

У меня есть метод, который я хочу ждать, но я не хочу вызывать эффект домино, который может вызвать любой вызов этого метода вызова и ждать его. Например, у меня есть этот метод:Как я могу ожидать метода async без модификатора async в этом родительском методе?

public bool Save(string data) 
{ 
    int rowsAffected = await UpdateDataAsync(data); 
    return rowsAffected > 0; 
} 

Я звоню:

public Task<int> UpdateDataAsync() 
{ 
    return Task.Run(() => 
    { 
    return Data.Update(); //return an integer of rowsAffected 
    } 
} 

Это не будет работать, потому что я должен поставить «асинхр» в методе подписи для Save(), а затем я могу 't return bool Мне нужно сделать это Task<bool>, но я не хочу, чтобы кто-то ждал метода Save().

Есть ли способ приостановить выполнение кода, например, ждать или как-то ждать этого кода без модификатора async?

+2

Мне было бы очень досадно, если бы вы дали мне доступ к методу «Сохранить», который заблокировал мой поток, что заставило меня обернуть вызов в «Задачу», что именно то, что вы могли бы вернуть мне в первую очередь , Просто говорю. –

ответ

7

Как я могу ожидать async-метода без модификатора async в этом родительском методе?

Это как просить «как я могу написать приложение с использованием C#, но не принимая зависимость от какого-либо времени выполнения .NET?»

Короткий ответ: не делайте этого.

Действительно, что вы делаете здесь принимает естественно-синхронную метод (Update), делая его асинхронным, запустив его на поток пула потоков (UpdateDataAsync), а затем Вы желаете, чтобы заблокировать на нем сделать асинхронный метод синхронным (Save). Серьезные красные флаги.

Я рекомендую вам внимательно изучить знаменитую пару постов Стивена Тоуба should I expose asynchronous wrappers for my synchronous methods и should I expose synchronous wrappers for my asynchronous methods. Ответ на оба вопроса - «нет», хотя Стивен Тууб объясняет несколько вариантов сделать это, если вам действительно нужно.

Это «действительно необходимо» должно быть зарезервировано для уровня приложения. Я предполагаю, что эти методы (Update, UpdateDataAsync и Save) находятся в разных слоях приложения (например, в модели данных/данных/представления данных). Уровни службы данных/данных не должны выполнять синхронные/асинхронные преобразования. Модель представления (специфичный для приложения) является единственной, у которой есть оправдание для такого преобразования - и она должна делать это только в крайнем случае.

+0

Что делать, если я пишу тестовый пример, где я помещал материал в базу данных (с драйвером Async), а затем сразу же прочитал его? Просто говоря, есть законные варианты использования синхронного программирования. – Hypershadsy

+0

@ Гипершадсы: Почему вы не могли сделать это асинхронно? –

+0

Вы можете написать асинхронные тестовые примеры? – Hypershadsy

3

Редактировать: этот ответ был до Task.Run добавлен. С этим дополнительным контекстом сценарий лучше всего описывается как «не делай этого».


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

Для защиты от этого трудно, но вы, вероятно, должны всегда указывать таймаут с вызовом .Wait() - на всякий случай.

+0

Спасибо, я использую Task.Run - я обновил свой вопрос, чтобы показать второй метод – Neal

+0

@ Нил с редактированием, я бы сказал, просто «не делай этого» - вы добавляете нить без всякой причины. Вы могли бы также выполнить эту работу в потоке, который будет сидеть в ожидании. –

+2

@ Нил: Марк абсолютно прав; по сути, то, что вы здесь делаете, - это нанять кого-то, кто ждет от вашего имени, а затем ждет, пока они не сделают свою работу, которая ждет от вашего имени. Вы бы не наняли кого-то, чтобы сделать это в реальной жизни, поэтому не делайте этого здесь. Если вам нужно ждать синхронно, чтобы задача была выполнена, сделайте это; если вы хотите продолжать выполнять работу, пока вы ждете, тогда «подождите». –

Смежные вопросы