我想最大限度地减少相互等待的任务的调度,而不是显示它是一个任务,我该如何改变我的TestOption1来返回一个调用方法的任务?

[TestClass()]
public class SqlServerTests
{
public const string Membership = "Data Source=LocalHost;Initial Catalog=tempdb;Integrated Security=True;";
[TestMethod()]
public async Task ContinueWithTest()
{
using CancellationTokenSource cts = new CancellationTokenSource();
//warm up so pooling is enabled on all 3 methods
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "set nocount on";
con.Open();
cmd.ExecuteNonQuery();
}
var sw2 = System.Diagnostics.Stopwatch.StartNew();
await TestOption2(cts.Token).ConfigureAwait(false);
sw2.Stop();
//allow the benefit of the doubt for the slower and give it cashed plans
var sw3 = System.Diagnostics.Stopwatch.StartNew();
await TestOption3(cts.Token).ConfigureAwait(false);
sw3.Stop();
Assert.IsTrue(sw2.ElapsedTicks < sw3.ElapsedTicks, "Stopwatch 2 {0} Stopwatch 3 {1}", sw2, sw3);
var sw1 = System.Diagnostics.Stopwatch.StartNew();
await TestOption1(cts.Token).ConfigureAwait(false);
sw1.Stop();
Console.WriteLine($"TestOption1: No internal awaits {sw1.ElapsedTicks:N0} ticks");
Console.WriteLine($"TestOption2: 1x internal await {sw2.ElapsedTicks:N0} ticks");
Console.WriteLine($"TestOption3: 2x internal await {sw3.ElapsedTicks:N0} ticks");
Assert.IsTrue(sw1.ElapsedTicks < sw2.ElapsedTicks, "Stopwatch 1 {0} Stopwatch 2 {1}", sw1, sw2);
Assert.IsTrue(sw1.ElapsedTicks < sw3.ElapsedTicks, "Stopwatch 1 {0} Stopwatch 3 {1}", sw1, sw3);
}
private static Task TestOption1(CancellationToken cancellationToken = default)
{
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "set nocount on";
return con.OpenAsync(cancellationToken)//fails as it does not wait for the db to open....
.ContinueWith((t) => cmd.ExecuteNonQuery()
, cancellationToken
, continuationOptions: TaskContinuationOptions.ExecuteSynchronously
, scheduler: TaskScheduler.Default);
}
}
private static async Task TestOption2(CancellationToken cancellationToken = default)
{
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "set nocount on";
await con.OpenAsync(cancellationToken)
.ContinueWith((_) => cmd.ExecuteNonQuery(), cancellationToken).ConfigureAwait(false);
}
}
private static async Task TestOption3(CancellationToken cancellationToken = default)
{
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "set nocount on";
await con.OpenAsync(cancellationToken).ConfigureAwait(false);
await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}
}我希望能够做这样的事情
[TestMethod]
public async Task TestContinueWithDelegate()
{
var data = await TestOptionReturn().ConfigureAwait(false);
Assert.IsNotNull(data);
}
private static Task<object> TestOptionReturn(CancellationToken cancellationToken = default)
{
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "Test1";
return con.OpenAsync(cancellationToken)//fails as it does not wait for the db to open....
.ContinueWith(delegate { return cmd.ExecuteScalar(); }
, cancellationToken
, continuationOptions: TaskContinuationOptions.ExecuteSynchronously
, scheduler: TaskScheduler.Default);
}
}以下测试失败,因为数据库未打开

等待公共异步任务TestContinueWithDelegate() {使用新的cts = TestMethod TestContinueWithDelegate();var CancellationTokenSource =使用var读取器的等待数据=等待TestMethod Assert.IsNotNull(数据);Assert.IsTrue(reader.Read());}
private static Task<object> TestOptioDDL(CancellationToken cancellationToken = default)
{
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "TestOutput";
cmd.Parameters.Add(new SqlParameter("Data", System.Data.SqlDbType.DateTime) { IsNullable = true, Direction = System.Data.ParameterDirection.Output });
return con.OpenAsync(cancellationToken)//fails as it does not wait for the db to open....
.ContinueWith(delegate
{
cmd.ExecuteScalar();
return cmd.Parameters[0].Value;
}
, cancellationToken
, continuationOptions: TaskContinuationOptions.ExecuteSynchronously
, scheduler: TaskScheduler.Default);
}
}
private static Task<SqlDataReader> TestOptionOutput(CancellationToken cancellationToken = default)
{
using (var con = new SqlConnection(Membership))
using (var cmd = con.CreateCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "select * from sys.databases";
cmd.Parameters.Add(new SqlParameter("Data", System.Data.SqlDbType.DateTime) { IsNullable = true, Direction = System.Data.ParameterDirection.Output });
return con.OpenAsync(cancellationToken)//fails as it does not wait for the db to open....
.ContinueWith(delegate
{
return cmd.ExecuteReader();
}
, cancellationToken
, continuationOptions: TaskContinuationOptions.ExecuteSynchronously
, scheduler: TaskScheduler.Default);
}
}发布于 2020-04-09 19:58:32
TestOption3是最好的选择。优化可维护性,而不是在I/O高度受限的任务上节省几毫秒。
也就是说,您的连接是关闭的,因为您的连接正在被before the tasks complete处理(甚至可能在它打开之前!)。如果要删除async和await,则需要处理方法的重写,以便在任务完成后运行using结尾处的处理。
https://stackoverflow.com/questions/61118686
复制相似问题