异步等待几个混乱

Adn*_*een 5 c# asynchronous task-parallel-library async-await

在体验4.5的新异步和等待功能时,我想在进一步讨论之前清除一些混淆.我一直在阅读不同的文章和关于SO的不同问题,它帮助我了解Async和Await如何工作.我将尝试将我的理解和困惑放在这里,并且如果某些代码教育我和其他正在寻找相同事物的人,我将非常感激.我用非常简单的措辞来讨论这个问题.

因此使用Async以便编译器知道由Async标记的方法包含Await操作(长操作).最新框架包含用于异步操作的不同新内置方法.

内置的Async函数(如connection.OpenAsync,ExecuteScalarAsync等)与Await关键字一起使用.我不知道这些异步方法的内部工作,但我强烈的猜测是,他们正在使用任务.

我可以将此作为Await与任何实现Task的方法的一般规则.因此,如果我需要创建自己的执行长操作的方法,那么我将创建它作为任务,当它被调用时,我将使用Await Keyword吗?

第二个最重要的是,将方法创建为异步或将其创建为任务的经验法则是什么.例如,

public void SampleMain()
{
    for (int i = 1; i <= 100; i++)
    {
         DataTable dt = ReadData(int id);
    }
}

public DataTable ReadData(int id)
{ 
     DataTable resultDT = new DataTable();

     DataTable dt1 = new DataTable();
     // Do Operation to Fill DataTable from first connection string
     adapter.Fill(dt1);

     DataTable dt2 = new DataTable();
     // Do Operation to Fill DataTable from first connection string
     adapter.Fill(dt2); 

     // Code for combining datatable and returning the resulting datatable
     // Combine DataTables
     return resultDT;
}

public string GetPrimaryConnectionString()
{
     // Retrieve connection string from some file io operations
     return "some primary connection string";
}

public string GetSecondaryConnectionString()
{
     // Retrieve connection string from some file io operations
     return "some secondaryconnection string";
}
Run Code Online (Sandbox Code Playgroud)

现在这是一个非常简单的场景,我根据我过去工作过的一些真实世界的应用程序创建了这个场景.所以我只是想知道如何使整个过程Async.

我应该将GetPrimaryConnectionString和GetSecondaryConnectionString作为任务并在ReadData中等待它们.ReadData也是一个任务吗?如何在SampleMain函数中调用ReadData?

另一种方法是在SampleMain中为ReadData创建一个Task,并运行该Task并跳过将其他方法转换为Task.这是好方法吗?它真的是异步吗?

Yuv*_*kov 7

因此使用Async以便编译器知道Async标记的方法包含Await操作

使用它async是为了使编译器具有从该方法创建状态机的指示.一种async方法可以没有await,仍然工作,但它会执行完全同步.

内置的Async函数(如connection.OpenAsync,ExecuteScalarAsync等)与Await关键字一起使用.我不知道这些异步方法的内部工作,但我强烈的猜测是,他们正在使用任务.

Task承诺将来完成工作.有几种方法可以创建Task.但是,Task并不是唯一可以代表异步操作的东西.如果您愿意,您可以自己创建一个等待它,它需要它来实现一个GetAwaiter返回类型实现的方法INotifyCompletion.

如果您想知道如何在框架中实现方法,则可以查看源代码.在这种特殊情况下,他们使用TaskCompletionSource<T>.

我应该将GetPrimaryConnectionString和GetSecondaryConnectionString作为任务并在ReadData中等待它们.ReadData也是一个任务吗?如何在SampleMain函数中调用ReadData?

检索连接字符串没有任何固有的异步.您通常(并非总是)使用async-await自然异步IO操作.在这种特殊情况下,唯一的实际异步操作是ReadData,如果你想让它异步,你可以使用SqlDataReader,它暴露了异步方法.

一个例子,取自ADO.NET团队的博客:

public static async Task<Product> GetProductAndReviewsAsync(
            int productID, int reviewsToGet)

{
    using (SqlConnection connection = new SqlConnection(ConnectionString))
    {
        await connection.OpenAsync();
        const string commandString = GetProductByIdCommand + ";" 
                                    + GetProductReviewsPagedById;

        using (SqlCommand command = new SqlCommand(commandString, connection))
        {
            command.Parameters.AddWithValue("productid", productID);
            command.Parameters.AddWithValue("reviewStart", 0); 
            command.Parameters.AddWithValue("reviewCount", reviewsToGet);
            using (SqlDataReader reader = await command.ExecuteReaderAsync())
            {
                if (await reader.ReadAsync())
                {
                    Product product = GetProductFromReader(reader, productID);
                    if (await reader.NextResultAsync())
                    {
                        List<Review> allReviews = new List<Review>();
                        while (await reader.ReadAsync())

                        {
                            Review review = GetReviewFromReader(reader);
                            allReviews.Add(review);
                        }
                        product.Reviews = allReviews.AsReadOnly();
                        return product;
                    }
                    else
                    {
                        throw new InvalidOperationException(
                            "Query to server failed to return list of reviews");
                    }
                }
                else
                {
                    return null;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)