gpt4 book ai didi

c# - 异步等待很少有混淆

转载 作者:太空狗 更新时间:2023-10-29 22:36:43 26 4
gpt4 key购买 nike

在体验 4.5 的新异步和等待功能时,我想在继续之前清除一些困惑。我一直在阅读不同的文章以及关于 SO 的不同问题,它帮助我理解 Async 和 Await 的工作原理。我会试着把我的理解和困惑放在这里,如果有人编码教育我和其他正在寻找相同东西的人,我将不胜感激。我正在用非常简单的措辞讨论这个问题。

所以使用Async是为了让编译器知道Async标记的方法中包含Await操作(Long操作)。最新框架包含用于异步操作的不同新内置方法。

connection.OpenAsync、ExecuteScalarAsync 等内置异步函数与 Await 关键字一起使用。我不知道这些异步方法的内部工作原理,但我强烈猜测它们在幕后使用的是任务。

我能否将此作为一般规则,即 Await 将与任何实现 Task 的方法一起使用。因此,如果我需要创建自己的执行长时间操作的方法,那么我会将其创建为 Task 并在调用它时使用 Await 关键字吗?

第二重要的是,将方法创建为 Async 或将其创建为任务的经验法则是什么。例如,

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";
}

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

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

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

最佳答案

So Async is used so that compiler know that method marked by Async contains Await operation

async用于使编译器指示从该方法创建状态机。一个async方法可以没有 await ,并且仍然有效,尽管它将完全同步执行。

The builtin Async functions like connection.OpenAsync, ExecuteScalarAsync etc are used with Await keyword. I don't know the inner working of these Async Methods but my strong guess is that under the hood they are using Tasks.

Task是对 future 要完成的工作的 promise 。有几种方法可以创建 Task .但是,Task不是唯一可以表示异步操作的东西。如果你愿意,你可以自己创建一个 awaitable,它只需要它来实现 GetAwaiter。返回实现 INotifyCompletion 类型的方法.

如果你想知道一个方法在框架中是如何实现的,you can view the source .在这种特殊情况下,他们使用 TaskCompletionSource<T> .

Should I make GetPrimaryConnectionString and GetSecondaryConnectionString as Tasks and Await them in ReadData. Will ReadData be also a Task? How to call ReadData in the SampleMain function?

检索连接字符串本质上并不异步。您通常(不总是)使用 async-await具有自然的异步 IO 操作。在这种特殊情况下,唯一实际的异步操作是 ReadData , 如果你想让它异步,你可以使用 SqlDataReader ,它公开了异步方法。

一个例子,取自ADO.NET teams blog :

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;
}
}
}
}
}

关于c# - 异步等待很少有混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31981565/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com