C # имеют асинхронный функцию синхронной функции или синхронной функции функции ASYNC

StackOverflow https://stackoverflow.com//questions/11674073

Вопрос

Я пишу библиотеку C # .NET 4.5 для выполнения общих операций базы данных SQL (резервное копирование, восстановление, выполнение скрипта и т. Д.). Я хочу иметь как синхронные, так и асинхронные функции для каждой операции, так как эта библиотека будет использоваться как приложениями консоли, так и для GUI, но я не хочу дублировать код везде. Так как я вижу это, у меня есть два варианта:

  1. Написать код, который выполняет работу в синхронной функции, а затем просто оберните его в задаче для Async-функции, как так:

    public void BackupDB(string server, string db)  
    {  
        // Do all of the work and long running operation here  
    }
    
    public async Task BackupDBAsync(string server, string db)  
    {  
        await Task.Factory.StartNew(() => BackupDB(server, db)).ConfigureAwait(false);  
    }
    

  2. Напишите код, который выполняет работу в асинхронной функции, и вызовите его из синхронной функции, используя .Wait ():

    public async Task BackupDBAsync(string server, string db)  
    {  
        // Do all of the work and long running operation here, asynchronously.  
    }
    
    public void BackupDB(string server, string db)  
    {  
        BackupDBAsync(server, db).Wait(); // Execution will wait here until async function finishes completely.  
    }
    

    - один вариант лучше другого? Это одна лучшая практика? Или есть ли другие (лучшие) альтернативы?

    Я знаю, что одно предупреждение для использования .wait () состоит в том, что все заявления avait в функции async должны использовать .configureawait (false), чтобы избежать тупиков ( Как обсуждалось здесь ), но с тех пор, как я пишу библиотеку, которая никогда не должна получить доступ к интерфейсу Или WebContext Я в безопасности, чтобы сделать это.

    Обратите внимание, что библиотека SQL обычно также имеет как синхронные, так и асинхронные функции, которые могут быть использованы, поэтому, если выполнение работы в функции синхронизации, я бы позвонил их функцию синхронизации, а если выполнять работу в Async Функция, я бы назвал свою async функцию.

    Мысли / предложения ценятся.

    - Редактировать: я также опубликовал этот вопрос на форумах MSDN здесь , чтобы попытаться получить официальный ответ MS -

Это было полезно?

Решение

Я хочу иметь как синхронные, так и асинхронные функции для каждой операции, поскольку эта библиотека будет использоваться как приложениями консоли, так и для GUI, но я не хочу дублировать код везде.

Лучший ответ: не.

Стивен Toub имеет два отличных сообщения в блоге на этой теме:

Другие советы

У меня была похожая ситуация, когда некоторые приложения необходимы, необходимые данные, которые будут загружаться синхронно и другие ASYC.Я решил создать интерфейс, который я позвонил My DataLoader:

public interface IIMViewModelDL {
    void LoadProjects(AssignProjects callback);
}
.

Обратный вызов TranseProjects - это просто простой делегат, который принимает возвращенный список проектов:

public delegate void AssignProjects(IEnumerable<Project> results);
.

Теперь красота этого состоит в том, что вы можете работать с интерфейсом, не зная, имеете ли вы в синхронизации или Async.

3 класса создаются: одна база, одна синхронизация и один async:

 public abstract class BaseViewModelDL {
    protected IEnumerable<Project> LoadProjects() {
        BaseServiceClient client = new BaseServiceClient();
        return client.Projects();
    }

public class SynchronousViewModelDL : BaseViewModelDL, IIMViewModelDL {
    public void LoadProjects(AssignProjects callback) {
        callback(base.LoadProjects());
    }

public class AsyncIMViewModelDL : BaseViewModelDL, IIMViewModelDL {
    public void LoadProjects(AssignProjects callback) {
        BackgroundWorker loadProjectsAsync = new BackgroundWorker();
        loadProjectsAsync.DoWork += new DoWorkEventHandler(LoadProjectsAsync_DoWork);
        loadProjectsAsync.RunWorkerCompleted += new RunWorkerCompletedEventHandler(LoadProjectsAsync_RunWorkerCompleted);
        loadProjectsAsync.RunWorkerAsync(callback);
    }

void LoadProjectsAsync_DoWork(object sender, DoWorkEventArgs e) {
        var results = new ObservableCollection<Project>(base.LoadProjects());
        e.Result = new object[] { results, e.Argument };
    }

    void LoadProjectsAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
        AssignProjects callback = (AssignProjects)((object[])e.Result)[1];
        IEnumerable<Project> results = (IEnumerable<Project>)((object[])e.Result)[0];
        callback(results);
    }
. Теперь в вашем приложении вы можете решить, как вы хотите загрузить данные ... Это может быть введено через контейнер IOC, но жестко закодирован для демонстрационных целей:
private ViewModelDataLoaders.IIMViewModelDL dataLoader = new ViewModelDataLoaders.AsyncIMViewModelDL();
.

Теперь ваш код вызова выглядит одинаково, и нет в том, является ли он async или Sync:

private void LoadProjects() {
        dataLoader.LoadProjects(
            delegate(IEnumerable<Project> results) {
                Projects = new ObservableCollection<Project>(results);
            });
    }
.

Я использую это регулярно для тестирования устройства (синхронизации), приложений WPF (ASYNC) и консольных приложений (синхронизация).

Там, кажется, не является точкой просто отметить метод Async без использования ждут. Маркировка его как Async не делает его асинхронным, это позволяет вам использовать ждет (код, выполненный в aquast, это то, что происходит асинхронно, а затем остальная часть асинхронизации также будет выполняться асинхронно) в организме метода: < / P >.

Как правило, метод, модифицированный ключевым словом Async, содержит по меньшей мере одно ждут выражения или оператора. Способ проходит синхронно, пока он не достигнет первого выражения ждут, в какой момент он приостановлен до тех пор, пока ожидаемая задача не будет завершена. Тем временем контроль возвращается к абоненту метода. Если метод не содержит ждут выражения или оператора, то он выполняет синхронно. Предупреждение о компиляторе предупреждает вас с любыми асинкоми методами, которые не содержат ждут, потому что эта ситуация может указывать на ошибку. Для получения дополнительной информации см. ПРЕДУПРЕЖДЕНИЕ COMBILER CS4014.

от: async / P >.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top