C# Task.WaitAll,获取所有异常和单个任务持续时间

C# Task.WaitAll,获取所有异常和单个任务持续时间,c#,asynchronous,exception-handling,stopwatch,C#,Asynchronous,Exception Handling,Stopwatch,我正在开发一个实用程序,它将使用ExecuteOnQueryAsync并行执行多个SQLCommand。该实用程序只应在所有请求完成时返回,因此我使用的是WaitAll 碰巧,该实用程序是一个SQL CLR存储过程这将禁止使用Task.Run() 我想捕获所有发生的个别异常,这些异常似乎工作正常。我现在尝试添加一种功能,可以同时获取阵列中每个任务的运行持续时间 这是代码的核心,没有任何经过时间信息: //命令数组已填充字符串数组(要执行的TSQL statements) Task[]tasks=

我正在开发一个实用程序,它将使用ExecuteOnQueryAsync并行执行多个SQLCommand。该实用程序只应在所有请求完成时返回,因此我使用的是WaitAll

碰巧,该实用程序是一个SQL CLR存储过程这将禁止使用Task.Run()

我想捕获所有发生的个别异常,这些异常似乎工作正常。我现在尝试添加一种功能,可以同时获取阵列中每个任务的运行持续时间

这是代码的核心,没有任何经过时间信息:

//命令数组已填充字符串数组(要执行的TSQL statements)
Task[]tasks=新任务[commands.Length];
试一试{
for(int i=0;i
现在,我正在努力找出如何获取每个ExecuteOnQueryAsync请求的运行时间

我的第一个想法是创建一个秒表数组,向executeSQL调用添加一个秒表参数,然后将watches数组传递给GetResults函数:

Task[]tasks=新任务[commands.Length];
秒表[]手表=新秒表[commands.Length];
试一试{
for(int i=0;i
我可以在调用executeSQL函数中的ExecuteOnQueryAsync之前启动秒表。但我什么时候能停止

这就是我试图解决这个问题所能做到的。我想我会添加一个延续来停止秒表,然后等待延续。但此代码无效(无法将类型“System.Runtime.CompilerServices.ConfiguredTaskAwaitable>”隐式转换为“System.Threading.Tasks.Task”)

var tasks=新任务[commands.Length];
var watches=新系统.Diagnostics.Stopwatch[commands.Length];
试一试{
for(int i=0;i{
表[i].Stop();
返回t;
},
TaskContinuationOptions.AttachedToParent
).配置等待(错误);
}
Task.WaitAll(任务);
}捕获(聚合异常){
// ...

好吧,答案是“简单”的解决方案确实有效,尽管我预计不会

下面是我对executeSQL函数的新定义,以及如何调用它

让我头疼的是异常处理。我想,如果语言本身将我的结果转化为任务,并在需要时神奇地将异常附加到任务中,那么,当然,如果我只是以正常的方式抛出异常(如下面的最后一块所示)会发生一些意想不到的事情(ExecuteOnQueryAsync返回一个任务,但我必须将结果分配给int,而不是任务,这一事实对我来说仍然很奇怪,我不喜欢它)

但是没有!它只是看起来起作用了

static async internal Task executeSql(字符串tsql、字符串connectionString、int commandTimeout、System.Diagnostics.Stopwatch){
int i=-1;
异常ex=null;
试一试{
使用(var con=newsqlconnection(connectionString)){
con.Open();
使用(var cmd=new SqlCommand(“设置xact_abort on;”+tsql,con)){
cmd.CommandType=System.Data.CommandType.Text;
cmd.CommandTimeout=CommandTimeout;
watch.Start();
i=await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}
}捕获(例外e){
ex=e;
}最后{
看,停;
如果(ex!=null){throw ex;}
}
返回i;
}
// ....
var tasks=新任务[commands.Length];
var watches=新系统.Diagnostics.Stopwatch[commands.Length];
试一试{
for(int i=0;i
任务
分配给一个变量,
在下一行对该变量进行配置等待
,然后将其添加到数组中。因为您已将所有内容都写在一行中,所以您正试图将
配置等待
的返回值添加到
任务
数组中。科林干杯。我发现尝试这样做真的很困惑确定语言何时“神奇地”我的意思是,你所说的一方面似乎非常明显,但另一方面,返回任务的异步函数实际上不能返回任务,而返回任务的异步函数实际上不能分配给任务。例如:
watch.Start();Task t=wait cmd.ExecuteNonQueryAsync().ConfigureAwait(false);watch.Stop();return t;
无效!。它不可分配,因为您正在等待
任务,然后尝试分配结果(即
int
)当它实际上只是
int
时,因为
wait
已经等待了