How to work correctly with a method that takes an asynchronous task as an argument, for example Task<NpgsqlConnection> ? Suppose I have an asynchronous method:

  public async Task<NpgsqlConnection> CreateConnectionAsync() { var connection = new NpgsqlConnection(this.ConnectionString); await connection.OpenAsync(); return connection; } 

And I need to get the NpgsqlConnection object in this method, which creates a command for the connection.

  public NpgsqlCommand NpgCommandCreator(NpgsqlConnection connection, string commandtext) { using (var connector = connection) { NpgsqlCommand COMMAND = connector.CreateCommand(); COMMAND.CommandText = commandtext; return COMMAND; } } 

The problem is that NpgsqlConnection and Task<NpgsqlConnection> not the same thing, how can I modify NpgCommandCreator that it can work with the object returned from CreateConnectionAsync ?

    2 answers 2

    Since your CreateConnectionAsync method returns Task<NpgsqlConnection> you can not upgrade anything, but rather wait for the asynchronous operation to complete using the await operator, and then transfer the resulting value to the NpgCommandCreator method.

    if await is applied to the result of a method call that returns Task<TResult> , then the type of await expression is TResult

    For example:

     public async void DoWorkAsync() { // ДоТидаСмся выполнСния асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ. // послС Π΅Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Ρ‚ΠΈΠΏΠ° NpgsqlConnection. var connection = await CreateConnectionAsync(); var myCommandText = "SELECT Name FROM Users"; // ΠŸΠ΅Ρ€Π΅Π΄Π°Π΅ΠΌ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄. var command = NpgCommandCreator(connection, myCommandText); } 
    • In this case, the connection is made asynchronously, and the request is executed synchronously. It is possible that the execution of the request also needs to be done asynchronously. - Tyler Durden
    • @TylerDurden but where did you see the query execution here? First a connection is created, then a command is created that will be executed within the specified connection. But the command does not start. - sp7
    • When transferring the connection 'NpgCommandCreator', I assumed that the request was fulfilled, I am wrong (premature judgment) - Tyler Durden

    When creating methods using the async / await model, the entire call chain should be created using the async / await model. In other words, async / await should be cross-cutting . for example

     async Task<int> FirstMethod() { await Task.Delay(100); return 1; } async Task<int> SecondMethod() { await Task.Delay(100); return 2; } async Task<int> UseBothMethods() { var first = await FirstMethod();//Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ высвобоТдаСтся ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π½ΡΡ‚ΡŒΡΡ Ρ‡Π΅ΠΌ-Ρ‚ΠΎ Π΅Ρ‰Π΅, ΠΏΠΎΠΊΠ° FirstMethod() Π½Π΅ Π²Π΅Ρ€Π½Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ var second = await SecondMethod();Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΠΏΠΎΡ‚ΠΎΠΊ высвобоТдаСтся ΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°Π½ΡΡ‚ΡŒΡΡ Ρ‡Π΅ΠΌ-Ρ‚ΠΎ Π΅Ρ‰Π΅, ΠΏΠΎΠΊΠ° SecondMethod() Π½Π΅ Π²Π΅Ρ€Π½Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ return first+second; } 

    If the UseBothMethods method is created without using async / await, then we will have to wait for the FirstMethod and SecondMethod execution, thereby suspending (freezing) the execution flow.

     Task<int> UseBothMethods() { var first = FirstMethod().Result; // ΠΆΠ΄Π΅ΠΌ 100 мс ΠΏΠΎΠΊΠ° Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒΡΡ ΠΌΠ΅Ρ‚ΠΎΠ΄. ΠŸΠΎΡ‚ΠΎΠΊ Π·Π°ΠΌΠΎΡ€ΠΎΠΆΠ΅Π½ ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚ var second = SecondMethod().Result;// ΠΆΠ΄Π΅ΠΌ 100 мс ΠΏΠΎΠΊΠ° Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒΡΡ ΠΌΠ΅Ρ‚ΠΎΠ΄. ΠŸΠΎΡ‚ΠΎΠΊ Π·Π°ΠΌΠΎΡ€ΠΎΠΆΠ΅Π½ ΠΈ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚ return first+second; } 

    If async / await is not done end-to-end, it will disrupt the use of the pattern and will deprive us of the benefits of asynchronous waiting for the execution of "long" methods, which is to release the thread to do any work.
    Now I will explain how all this relates to the current issue. The answer is, if you create async / await end-to-end, as it should be, then questions on the type of what the author had, simply will not arise.