DataAdapter填充异步异常

3
我有一组异步方法,用于处理大量数据库查询和编译,速度非常快。这些方法在大多数情况下都非常出色,并且对我的软件产生了很好的效果。然而,最近我遇到了一个小问题:偶尔用户会出错,导致软件拉取数据的时间范围变得非常巨大,数据适配器在获取信息之前超时。通常,在同步方法中,您可以使用try/catch来处理此类问题,但我尝试过这种方法却没有成功。是否有一种异步处理异常的方法,使其像同步方法一样抛出异常,以便我的try/catch可以正常工作?
以下是我使用的数据适配器异步方法示例:
private async Task<DataTable> WWQuery2Run
(string A, string B, string C, string D)
{
  using ( var conn = new System.Data.SqlClient.SqlConnection(ReportResources.ConnString) )
  {
    var temp = new DataTable();
    var DA = new SqlDataAdapter(string.Format(ReportResources.Instance.CureInfoQueries["WWQuery2"], A, B, C, D), conn);
    await Task.Run(() => DA.Fill(temp));
    return temp;
  }
}

编辑:

我意识到,尝试处理超时异常并不是一个好的实践方式。因此,我添加了一种方法,在进入显示异步方法之前计算持续时间,并警告用户该操作需要的时间长度,让他们有选择中止编译的选项。有了这个方法,如果用户选择继续,我将查询的超时时间增加到可以覆盖所有情况(除了最糟糕的情况)。我还在程序中添加了一些项目的描述,包括计算的持续时间,以便用户在尝试查询和编译之前就知道操作所需的时间。

感谢@Murad Garibzada的协助。


目前正在努力将异步功能应用于.NET中的DataAdapter.Fill。请访问https://github.com/dotnet/runtime/issues/22109了解更多信息。 - Lachlan Ennis
3个回答

10

除了增加命令超时时间,您还可以使用try / catch块。由于您正在等待,因此在WWQuery2Run完成之前,控制不会返回到调用代码。如果WWQuery2Run抛出SomeException,它将被代码捕获和处理。

private async Task<DataTable> WWQuery2Run(string A, string B, string C, string D)
{
    try 
    {
        using ( var conn = new System.Data.SqlClient.SqlConnection(ReportResources.ConnString) )
        {
            var temp = new DataTable();
            var DA = new SqlDataAdapter(string.Format(ReportResources.Instance.CureInfoQueries["WWQuery2"], A, B, C, D), conn);
            await Task.Run(() => DA.Fill(temp));
            return temp;
        } 
    } 
    catch (SomeException ex)
    {
        // handle exception
    }
}

2

因为你的连接conn被包裹在一个using语句中,所以在调用Fill之前,它有可能被释放。

可能像以下这样会起作用:

private async Task<DataTable> WWQuery2Run (string A, string B, string C, string D)
{
  var temp = new DataTable();
  await Task.Run(() => {
    using ( var conn = new System.Data.SqlClient.SqlConnection(ReportResources.ConnString) )
    {
      var DA = new SqlDataAdapter(string.Format(ReportResources.Instance.CureInfoQueries["WWQuery2"], A, B, C, D), conn);
      DA.Fill(temp)
    }
  });
  return temp;
}

0

你可以像下面这样增加适配器命令超时时间:

 SqlDataAdapter adapter= new SqlDataAdapter(strSQLString, conUS);
 adapter.SelectCommand.CommandTimeout=120;

处理异常:

 private async Task<DataTable> WWQuery2Run
   (string A, string B, string C, string D)
  {
      using ( var conn = new System.Data.SqlClient.SqlConnection(ReportResources.ConnString) )
 {
var temp = new DataTable();
var DA = new SqlDataAdapter(string.Format(ReportResources.Instance.CureInfoQueries["WWQuery2"], A, B, C, D), conn);


Task task = new Task(() => DA.Fill(temp));
 try
{
    task.Wait();
}
catch (Exception ae)
{



}

return temp;
}
}  

没错,那样做是可以的,但如果可能的话,我更希望它能超时,并在超时后提醒用户出现问题。我知道我可能在要求一些不合适的东西,但我的用户有点迟钝,如果时间超长,他们会认为是软件出了问题而不是操作员的错误。 - ARidder101
非常简单,只需访问以下链接:https://msdn.microsoft.com/zh-cn/library/dd537614(v=vs.110).aspx - Murad
你能给个例子,说明一下那个链接中的方法是如何工作的吗?我试过几次运用那个方法,但似乎那个链接中的方法不适用于异步方法/任务,无法解决我的问题。 - ARidder101
请检查上面的答案。 - Murad
我尝试了那个方法以及它的几个变种,但结果只是让我的程序无限地停滞不前。它从来没有抛出过异常。 - ARidder101
Task.Wait是一个阻塞调用,而MSDN上的示例没有使用async。 - William Xifaras

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接