C# 整洁的SqlException和未观察到的异常

C# 整洁的SqlException和未观察到的异常,c#,.net,task-parallel-library,dapper,C#,.net,Task Parallel Library,Dapper,当T-SQL过程引发错误(SQLException)时,我对以下代码有问题 var result=await conn.QueryMultipleAsync(“Inventory.uspLoadItems”,新增 { dbId=obj.myId, }, commandType:commandType.StoredProcess); var items=wait result.ReadAsync(); var specificItems=MyCustomMapper.MapTo((动态)项);

当T-SQL过程引发错误(SQLException)时,我对以下代码有问题

var result=await conn.QueryMultipleAsync(“Inventory.uspLoadItems”,新增
{
dbId=obj.myId,
},
commandType:commandType.StoredProcess);
var items=wait result.ReadAsync();
var specificItems=MyCustomMapper.MapTo((动态)项);
我使用的是简洁的1.50.2版

进程被抛出到一个未观察到的异常中

我可以一直跟踪异常,直到WebApi控制器方法。但是当控制器方法存在时,另一个(生成和未完成)线程继续在
var items=wait items.ReadAsync()处执行即使WebApi会话已终止(GC已收集?)。(由于我误解了Parallel Stack窗口中的信息,文本被删除。异常在ReadAsync失败,而不是QueryMultipleAsync,因此在异常后没有继续)。
看起来像是整洁的线程问题,但我不确定

更新

我在MicrosoftConnect上找到了与此主题高度相关的以下链接。

所以,对于任何其他经历过这种行为的人来说。您必须等待下一次.NET更新

这不是一个衣冠楚楚的问题,但如果衣冠楚楚的出资人能找到一份临时工作,那就太好了:)

现在,我将所有ReadAsync更改为Read(synchronous),以避免这个SqlDataReader错误

另一个(生成和未完成)线程继续在var items=await items.ReadAsync()处执行

听起来像是所有这些代码所在的函数都是异步执行的,不会等待或与之同步。主请求在该函数仍在运行时完成(这不是猜测,您的观察证明代码在控制器完成后执行)。然后,如果此代码崩溃,则无法观察到异常

忽略未观察到的异常是不正确的修复方法。无论如何,我建议这样做,但正确的修复方法是等待此代码所属的任务


因为您的代码仍在运行,所以它不是一个框架bug。您链接到的bug可能会导致框架代码稍后不被注意地执行,但它不会导致语句在等待之后(再次)运行。

不要认为这是线程问题。wait result.ReadAsync()将在单独的线程中调用,因为在此之前还有另一个wait。你能在这里发布异常吗?
Async wait
,除了调用线程之外没有线程,检查:你能尝试一下
QueryMultiple的同步版本吗?
,并检查是否观察到类似的异常。在这种情况下,您如何知道Web API会话是垃圾收集的(没有办法知道),只是上下文丢失了。在后台,IO进程位于上,因为并没有可用的处理程序,它可能会给出一个未观察到的异常。您是否在调用堆栈顶部的Web API控制器中等待接收调用结果,这在本例中很重要。@MrinalKamboj我尝试在控制台应用程序中复制,但没有成功。也许整洁毕竟是无辜的。现在我怀疑这个问题与Katana(OWIN selfhost)、WebApi2和/或控制器方法中CancellationToken注入的使用有关。当存储过程引发错误(SQLException)时,问题似乎会表现出来。我需要进一步调查,看看“等待链”中的所有代码会很有趣。你声称等待的一切都是正确的,但我坚持认为不是。可能有很多微妙的问题……我同意你的看法。我现在明白我的观察可能是错误的。当我的TaskScheduler.UnobservedTaskeException处理程序中的代码暂停时,我正在使用ParallelStacks窗口。在导致异常的线程中,控制器方法完成后,ReadAsync上会显示一条绿线(执行行)。我认为QueryMultipleAsync应该引发SqlException,因此错误地假设代码在异常之后继续。似乎只有在ReadAsync和Parallel Stack窗口正确显示异常的来源时才会引发异常。
    var result = await conn.QueryMultipleAsync("Inventory.uspLoadItems", new
    {
        dbId = obj.myId,
    },
    commandType: CommandType.StoredProcedure);
    var items = await result.ReadAsync();
    var specificItems = MyCustomMapper.MapTo<MyItem>((dynamic)items);