@ Игорь Нет, точно такое же поведение с

ыполнении вызовов к SQL Server, которые на самом деле делают вещи, которые требуют времени,SqlDataReader.ReadAsync() работает синхронно для меня. Есть ли способ заставить его работать асинхронно или это мой единственный вариант вызвать его вTask.Run()?

Вот репродукция. Он использует winforms, чтобы продемонстрировать, что вызов блокирует поток GUI. Обратите внимание, что T-SQL должен что-то делатьэто не воспроизводится сWAITFOR DELAY '00:00:20'.

using System;
using System.Configuration;
using System.Data.Common;
using System.Data.SqlClient;
using System.Threading.Tasks;
using System.Windows.Forms;

static class SqlDataReaderReadAsyncProgram
{
    static async void Form_Shown(object sender, EventArgs e)
    {
        var form = (Form)sender;
        // Declare your connection string in app.config like
        // <connectionStrings><remove name="LocalSqlServer"/><add name="LocalSqlServer" connectionString="Data Source=localhost\SQLEXPRESS;Integrated Security=true"/></connectionStrings>
        using (DbConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings[0].ConnectionString))
        {
            form.Text = "connecting…";
            await connection.OpenAsync();
            form.Text = "connected!";
            // Install a stored procedure.
            using (var command = connection.CreateCommand())
            {
                command.CommandText = "SET NOCOUNT ON"
                    + " SELECT 'a'"
                    + " DECLARE @t DATETIME = SYSDATETIME()"
                    + " WHILE DATEDIFF(s, @t, SYSDATETIME()) < 20 BEGIN"
                    + "   SELECT 2 x INTO #y"
                    + "   DROP TABLE #y"
                    + " END"
                    + " SELECT 'b'";
                form.Text = "executing…";
                using (var reader = await command.ExecuteReaderAsync())
                {
                    form.Text = "reading…";
                    do
                    {
                        // Blocks on the second call until the second resultset is returned by SQL Server
                        while (await reader.ReadAsync())
                        {
                        }
                    } while (await reader.NextResultAsync());
                    form.Text = "done!";
                }
            }
        }
        await Task.Delay(TimeSpan.FromSeconds(5));
        form.Close();
    }

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var form = new Form();
        form.Shown += Form_Shown;
        Application.Run(form);
    }
}

Когда я запускаю это, окно становится «(не отвечает)» на 20 секунд, прежде чем сообщать о том, что это сделано (обратите внимание, что при отладке в VS текст «(не отвечает)» не появляется, но он все равно останавливается). Если я отлаживаю в VS и ломаю его, пока он заморожен, я вижу, что он сидит со стеком вызовов, который выглядит так:

    [Managed to Native Transition]  
    System.Data.dll!SNINativeMethodWrapper.SNIReadSyncOverAsync(System.Runtime.InteropServices.SafeHandle pConn, ref System.IntPtr packet, int timeout) Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()   Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()   Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()   Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadByteArray(byte[] buff, int offset, int len, out int totalRead)    Unknown
    System.Data.dll!System.Data.SqlClient.TdsParserStateObject.TryReadInt64(out long value) Unknown
    System.Data.dll!System.Data.SqlClient.TdsParser.TryProcessDone(System.Data.SqlClient.SqlCommand cmd, System.Data.SqlClient.SqlDataReader reader, ref System.Data.SqlClient.RunBehavior run, System.Data.SqlClient.TdsParserStateObject stateObj)    Unknown
    System.Data.dll!System.Data.SqlClient.TdsParser.TryRun(System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, out bool dataReady)  Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.TryHasMoreRows(out bool moreRows)   Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.TryReadInternal(bool setTimeout, out bool more) Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.ReadAsync.AnonymousMethod__0(System.Threading.Tasks.Task t) Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.InvokeRetryable<bool>(System.Func<System.Threading.Tasks.Task, System.Threading.Tasks.Task<bool>> moreFunc, System.Threading.Tasks.TaskCompletionSource<bool> source, System.IDisposable objectToDispose)   Unknown
    System.Data.dll!System.Data.SqlClient.SqlDataReader.ReadAsync(System.Threading.CancellationToken cancellationToken) Unknown
    System.Data.dll!System.Data.Common.DbDataReader.ReadAsync() Unknown
>   SqlDataReaderReadAsync.exe!SqlDataReaderReadAsyncProgram.Form_Shown(object sender, System.EventArgs e) Line 36  C#
    [Resuming Async Method] 

(далее обрезан для краткости).

ЦелыйReadSyncOverAsync материал выглядит особенно подозрительно для меня. Как будто SqlClient предполагает, что синхронное чтение не будет блокироваться, как будто он не знает, как использовать неблокирующий ввод-вывод или что-то в этом роде. Тем не менее, при просмотре эталонного источника или декомпиляции с помощью JustDecompile, похоже, что должна быть асинхронная поддержка, но просто почему-то эвристически / откатно решил ее не использовать.

Итак, как мне получить *Async() вещи в SqlClient на самом деле быть асинхронными? Я думал, что эти методы должны были позволить мне писать программы без графического интерфейса без необходимости использованияTask.Run() потому что упаковка синхронных вещей вTask.Run() просто делать их асинхронными - бессмысленные накладные расходы ...?

Я использую .net-4.7.02542.

Я предполагаю, что это ошибка .net и отправилподключиться # 3139210 (РЕДАКТИРОВАТЬ: подключение не работает, у меня есть проект вhttps://github.com/binki/connect3139210).

ОБНОВИТЬ: Microsoft признает ошибку и исправит ее в .net-4.7.3.Я использовал случай «Технической поддержки» из подписки VS, чтобы сообщить об ошибке и получить эту информацию.

Ответы на вопрос(0)

Ваш ответ на вопрос