async / await
От: Iso12  
Дата: 22.05.17 13:52
Оценка:
Добрый день !

Для коротких запросов к БД использую async / await. Примерно вот так:

        public async Task<bool> MyRequestToBDAsync()
        {
           return await Task<bool>.Run(() =>
           {
                 Func1();
                 return Func2();
           });
        }


Есть функция обработки данных, которая требует определенное количество времени для исполнения.Поэтому вызываем функцию в отдельном Thread из пула. Но и там же нужно получить данные из БД.
Получается следующая конструкция, которая роботает, но мне не нравится:

        private void WorkFunc()
        {        
            Task.Run(async () =>
            {
               var dat1 = await MyRequestToBDAsync1();
               var dat2 = await MyRequestToBDAsync2();
               NeedLongTime(dat1, dat2);

            });
        }


await в этом месте не имеет смысла.
Вот думаю как быть?
Переписать запросы к БД? Типа:
        public bool MyRequestToBD()
        {
           Func1();
           return Func2();
        }
        public async Task<bool> MyRequestToBDAsync()
        {
           return await Task<bool>.Run(() =>
           {
              return MyRequestToBD();
           });
        }


и потом использовать в Worker thread.
Re: async / await
От: Jack128  
Дата: 22.05.17 14:19
Оценка:
Здравствуйте, Iso12, Вы писали:

I>await в этом месте не имеет смысла.



Почему не имеет смысла ? Ты хочешь запустить запросы к базе в параллель?? Тогда так:

var dat1 = MyRequestToBDAsync1();
var dat2 = MyRequestToBDAsync2();
await Task.WhenAll(dat1, dat2)
NeedLongTime(dat1.Result, dat2.Result);
Отредактировано 22.05.2017 14:19 Jack128 . Предыдущая версия .
Re: async / await
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.05.17 14:42
Оценка:
Здравствуйте, Iso12, Вы писали:

Вообще то есть асинхронные запросы
https://msdn.microsoft.com/en-us/library/jj819165(v=vs.113).aspx
http://www.infoworld.com/article/2902406/microsoft-net/asynchronous-operations-in-ado-net.html
и солнце б утром не вставало, когда бы не было меня
Re[2]: async / await
От: Iso12  
Дата: 22.05.17 21:49
Оценка:
Здравствуйте, Jack128, Вы писали:


J>Почему не имеет смысла ? Ты хочешь запустить запросы к базе в параллель??


Нет, это выполняется последовательно.
Re[2]: async / await
От: Iso12  
Дата: 22.05.17 21:53
Оценка:
Здравствуйте, Serginio1, Вы писали:


S>Вообще то есть асинхронные запросы

S>https://msdn.microsoft.com/en-us/library/jj819165(v=vs.113).aspx
S>http://www.infoworld.com/article/2902406/microsoft-net/asynchronous-operations-in-ado-net.html

Спасибо за ссылку, но EF мы не используем.
Re[3]: async / await
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 23.05.17 06:59
Оценка:
Здравствуйте, Iso12, Вы писали:

I>Здравствуйте, Serginio1, Вы писали:



S>>Вообще то есть асинхронные запросы

S>>https://msdn.microsoft.com/en-us/library/jj819165(v=vs.113).aspx
S>>http://www.infoworld.com/article/2902406/microsoft-net/asynchronous-operations-in-ado-net.html

I>Спасибо за ссылку, но EF мы не используем.


Ну вообще то у Command полно асинхронных методов

https://msdn.microsoft.com/ru-ru/library/system.data.common.dbcommand_methods(v=vs.110).aspx

https://stackoverflow.com/questions/26303954/how-to-make-two-sql-queries-really-asynchronous
и солнце б утром не вставало, когда бы не было меня
Re: async / await
От: Sinatr Германия  
Дата: 23.05.17 07:52
Оценка: 2 (1)
Здравствуйте, Iso12, Вы писали:

I>
public async Task<bool> MyRequestToBDAsync()
{
    return await Task<bool>.Run(() =>
    {
        Func1();
        return Func2();
    });
}


Так делать не надо, никогда не делайте асинхронные обертки для синхронных методов, caller может сам создать Task или вызвать метод из уже созданного. Просто сделайте синхронный метод, если используются синхронные методы для доступа к бд.

I>
private void WorkFunc()
{        
    Task.Run(async () =>
    {
        var dat1 = await MyRequestToBDAsync1();
        var dat2 = await MyRequestToBDAsync2();
        NeedLongTime(dat1, dat2);
    });
}


Снова не правильно. Чтобы получить результат вызова асинхронного метода см. Task.Result (есть нюансы с контекстом). В частности ваш метод можно переписать как-то так:

private void WorkFunc()
{
    var dat1 = MyRequestToBDAsync1().Result; // ждем
    var dat2 = MyRequestToBDAsync2().Result; // ждем
    NeedLongTime(dat1, dat2);
}

Проще всего сделать методы MyRequestToBD...() синхронными и вызывать их последовательно.

Если запросы 1 и 2 можно выполнить одновременно, то имеет смысл вызывать их паралельно, к примеру:

private void WorkFunc()
{
    var task1 = Task.Run(() => MyRequestToBD1());
    var task2 = Task.Run(() => MyRequestToBD2());
    Task.WaitAll(new[] {task1, task1});
    NeedLongTime(task1.Result, task2.Result);
}
---
ПроГLамеры объединяйтесь..
Отредактировано 23.05.2017 7:54 Sinatr . Предыдущая версия .
Re[2]: async / await
От: Jack128  
Дата: 23.05.17 13:07
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>Снова не правильно. Чтобы получить результат вызова асинхронного метода см. Task.Result (есть нюансы с контекстом). В частности ваш метод можно переписать как-то так:


S>
S>private void WorkFunc()
S>{
S>    var dat1 = MyRequestToBDAsync1().Result; // ждем
S>    var dat2 = MyRequestToBDAsync2().Result; // ждем
S>    NeedLongTime(dat1, dat2);
S>}
S>


А зачем вызывать .Result и иметь шанс на дедлок, есть можно написать await?
Re[4]: async / await
От: Iso12  
Дата: 23.05.17 15:12
Оценка:
Здравствуйте, Serginio1, Вы писали:


S>Ну вообще то у Command полно асинхронных методов


У меня проблема не что использовать, а как использовать.
Проблема в том, что в Worker Thread вызывается async функция. Получается плохой код, который хотелось бы исправить.
Re[2]: async / await
От: Iso12  
Дата: 23.05.17 15:36
Оценка:
Здравствуйте, Sinatr, Вы писали:


I>>
S>public async Task<bool> MyRequestToBDAsync()
S>{
S>    return await Task<bool>.Run(() =>
S>    {
S>        Func1();
S>        return Func2();
S>    });
S>}
S>


S>Так делать не надо, никогда не делайте асинхронные обертки для синхронных методов, caller может сам создать Task или вызвать метод из уже созданного. Просто сделайте синхронный метод, если используются синхронные методы для доступа к бд.


У меня немного другая конструкция. После return стоит await и если я правильно понимаю, то UI thread будет ждать завершения функции не блокируясь. Это больше относится к примеру ниже.
Но в этом случае как быть вот с этим, здесь пишут что надо делать именно так (пример RenderAsync).
Кто прав?


I>>
S>private void WorkFunc()
S>{        
S>    Task.Run(async () =>
S>    {
S>        var dat1 = await MyRequestToBDAsync1();
S>        var dat2 = await MyRequestToBDAsync2();
S>        NeedLongTime(dat1, dat2);
S>    });
S>}   
S>


S>Снова не правильно. Чтобы получить результат вызова асинхронного метода см. Task.Result (есть нюансы с контекстом). В частности ваш метод можно переписать как-то так:

S>
S>private void WorkFunc()
S>{
S>    var dat1 = MyRequestToBDAsync1().Result; // ждем
S>    var dat2 = MyRequestToBDAsync2().Result; // ждем
S>    NeedLongTime(dat1, dat2);
S>}
S>


Result не рекомендуют использовать из-за опасности нарваться на deadlock. Хотя в этом случае выполнение идёт в worker thread, a не в UI thread, поэтому такой опасности скорей не будет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.