在Run
中,我正在尝试将10,000个任务排队。 (这只是一个实验,所以我可以更好地理解async await
。)但是第一个循环需要三秒钟才能完成。我希望这样做会更快,因为我只是尝试将任务排队,然后在几行之后await
。 Run
仍在alreadyCompleted
中,因为任务似乎已同步运行。最后,仍然在Run
内,第二个循环需要1毫秒才能完成,再次显示任务已经运行。
如何在我允许使用Run
之前通过await
方法将要运行的任务排队的同时?我会了解我的某些任务是否在alreadyCompleted
被检查时已完成,但是似乎所有任务都已完成很奇怪。在ASP.NET Core 3,.NET Core 3控制台和.NET Framework控制台之间,此行为是一致的。谢谢。
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
public static class SqlUtility
{
public static async Task Run()
{
const int max = 10000;
Stopwatch sw1 = Stopwatch.StartNew();
Task<int>[] tasks = new Task<int>[max];
for(int i=0;i<max;i++)
{
tasks[i] = GetVideoID();
}
sw1.Stop();//ElapsedMilliseconds: 3169
bool alreadyCompleted = tasks.All(t => t.IsCompletedSuccessfully);//true
Stopwatch sw2 = Stopwatch.StartNew();
for (int i = 0; i < max; i++)
{
await tasks[i].ConfigureAwait(false);
}
sw2.Stop();//ElapsedMilliseconds: 1
}
public static async Task<int> GetVideoID()
{
const string connectionString =
"Server=localhost;Database=[Redacted];Integrated Security=true";
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("VideoID",SqlDbType.Int) { Value = 1000 }
};
const string commandText = "select * from Video where VideoID=@VideoID";
IAsyncEnumerable<object> values = GetvaluesAsync(connectionString,parameters,commandText,CancellationToken.None);
object videoID = await values.FirstAsync().ConfigureAwait(false);//1000
return (int)videoID;
}
public static async IAsyncEnumerable<object> GetvaluesAsync(
string connectionString,SqlParameter[] parameters,string commandText,[EnumeratorCancellation]CancellationToken cancellationToken)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
using (SqlCommand command = new SqlCommand(commandText,connection))
{
command.Parameters.AddRange(parameters);
using (var reader = await command.ExecuteReaderAsync()
.ConfigureAwait(false))
{
while (await reader.ReadAsync().ConfigureAwait(false))
{
yield return reader[0];
}
}
}
}
}
}
更新
运行.NET Core应用程序并使用max
为1,000时,alreadyCompleted
为假。实际上,查看每个任务的IsCompleted
,当前alreadyCompleted
所在的位置都没有完成任务。这就是我原本会发生的事情。
但是,如果max
设置为10,000(与原来一样),则alreadyCompleted
就是假的,就像上面一样。有趣的是,检查tasks[max - 1].IsCompleted
会产生false
(首先检查最后一个任务)。 tasks.All(t => t.IsCompletedSuccessfully)
最后检查最后一个结果,此时IsCompleted
是true
。