填充数据集异步

时间:2018-05-07 06:29:48

标签: c# multithreading ado.net dataset thread-safety

以下方法用于填充数据集。

如果我们以同步方式调用此方法,它工作正常。

但是现在我们需要以异步方式调用此方法。那么我需要做哪些更改,以便下面的方法可以正常工作而没有任何问题。

public DataSet Filldata(字符串ProcName,字符串TableName)     {         DataSet ds = new DataSet();         尝试         {             da = new SqlDataAdapter(ProcName,con);             if(con.State!= ConnectionState.Open)             {                 con.Open();             }             da.SelectCommand.CommandTimeout = 15000;             da.Fill(ds,TableName);         }         catch(Exception ex)         {             ErrorMsg = ex.Message.ToString();             HMISLogger.logger.Error(ex.Message.ToString()+"" + ProcName,ex);         }         最后         {             con.Close();             da.Dispose();         }         返回ds;     }

3 个答案:

答案 0 :(得分:0)

您可以使用以下内容,返回作为异步操作的任务

public Task<DataSet> FilldataAsync(string ProcName, string TableName)
{
    try
            {
                return Task.Run(() =>
                {
                    DataSet ds = new DataSet();
                    using (var da = new SqlDataAdapter(ProcName, con))
                    {
                        da.SelectCommand.CommandTimeout = 15000;
                        da.Fill(ds, TableName);
                        return ds;
                    }
                });
            }
            catch (Exception ex)
            {
                ErrorMsg = ex.Message.ToString();
                HMISLogger.logger.Error(ex.Message.ToString() + " " + ProcName, ex);
            }
}

您可以使用async / await关键字将其命名为

private async Task GetSomeData(string sSQL)
{
    DataSet results = await FilldataAsync(ProcName, TableName);
    //Populate once data received
    grdRes.DataSource = results.Tables[0];
}

答案 1 :(得分:0)

您可以将类级静态对象声明如下

private static object lockObject = new object();

并修改你的方法,如下所示,As Fill方法负责打开和关闭连接,我们可以在它之前添加lock语句。

 public DataSet Filldata(string ProcName, string TableName)
        {
            DataSet ds = new DataSet();
            try
            {

                da = new SqlDataAdapter(ProcName, con);
                da.SelectCommand.CommandTimeout = 15000;
                lock (lockObj)
                {
                    da.Fill(ds, TableName);
                }
            }            
            catch (Exception ex) {
                ErrorMsg = ex.Message.ToString();
                HMISLogger.logger.Error(ex.Message.ToString() + " " + ProcName, ex);
            }
            finally {
                con.Close();
                da.Dispose();
            }
            return ds;
        }

答案 2 :(得分:0)

您可以这样做:

DataSet ds = await Task.Run(() => FillData(spName, tableName)); 

但是该语句必须在某些异步函数内,即:

public async Task<DataSet> GetDataSetAsync() {
      ..... 
   } 

所以最终结果看起来像这样:

public async Task<DataSet> GetDataSetAsync() {

DataSet ds = await Task.Run(() => FillData(spName, tableName)); 

return ds;
} 

那是包装器,它只为您提供想法。您可能不应该这样做。我将Task.Run放在调用SqlDataAdapter .Fill的最低级别

这在.NetFrameWork WebAPI中将不起作用,但是只要您引用NuGet包System.Data.SqlClient 4.6.0,它就可以在.Net Core WebAPI和Core或常规.Net Console程序中工作。在.Net Framework WebAPI(非核心)中,由于进程在await语句中消失,因此await似乎在另一个线程中返回了DataSet。