使用异步.net 4.0返回DataTable
问题描述:
我有一个方法返回一个数据表。我认为使用.net 4.0我可以只是异步逻辑并返回数据。但是这段代码返回的是空的Datatable对象。任何想法这个代码有什么问题。使用异步.net 4.0返回DataTable
public DataTable GetData(string sql, string connectionName)
{
DataTable dt = (DataTable)GetDataAsync(sql, connectionName).AsyncState;
return dt;
}
private async Task<DataTable> GetDataAsync(string sql, string connectionName)
{
return await TaskEx.Run(() => { return FillData(sql, connectionName); });
}
private DataTable FillData(string sql, string connectionName)
{
SqlConnection conn = _connections.Where(w => w.ConnectionName == connectionName).Single().Connection;
SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
DataSet ds = new DataSet();
adp.Fill(ds);
return ds.Tables[0];
}
答
首先,你不能使用async
/await
与.NET 4或C#4,这是一个在C#5,有CTP版本里面装上的.NET 4的顶部的一个新功能,但也有一定的错误在那些CTP中 - 不要使用它们。您应该使用.NET 4.5的完整版本,其中包括C#5编译器。 (所有这一切都在Visual Studio 2012中)。第二,如Cuong Le所示,您正在使用任务的错误属性。 Result
属性是您如何得到Task<T>
的结果。
第三,使用Result
属性进行更改后,您会阻止提取表 - 使其无意义。这:
public DataTable GetData(string sql, string connectionName)
{
DataTable dt = (DataTable)GetDataAsync(sql, connectionName).Result;
return dt;
}
...在很大程度上等同于:
public DataTable GetData(string sql, string connectionName)
{
return FillData(sql, connectionName);
}
如果你要开始一个任务并立即等待就可以了,你可能也只是调用该方法同步。
答
如果要使用async
代码,则don't block on it。另外,请确保您使用的是Async Targeting Pack而不是Async CTP。
private async Task<DataTable> GetDataAsync(string sql, string connectionName)
{
return await TaskEx.Run(() => { return FillData(sql, connectionName); });
}
private async GetAndProcessDataAsync()
{
DataTable table = await GetDataAsync("my sql", "my connection name");
ProcessData(table);
}
答
我自己的源代码。
public static async Task<DataTable> GetDataTableAsync(this System.Data.Common.DbCommand command, CancellationToken cancellationToken, string tableName = null)
{
TaskCompletionSource<DataTable> source = new TaskCompletionSource<DataTable>();
var resultTable = new DataTable(tableName ?? command.CommandText);
DbDataReader dataReader = null;
if (cancellationToken.IsCancellationRequested == true)
{
source.SetCanceled();
await source.Task;
}
try
{
await command.Connection.OpenAsync();
dataReader = await command.ExecuteReaderAsync(CommandBehavior.Default);
resultTable.Load(dataReader);
source.SetResult(resultTable);
}
catch (Exception ex)
{
source.SetException(ex);
}
finally
{
if (dataReader != null)
dataReader.Close();
command.Connection.Close();
}
return resultTable;
}
您不能在.NET 4.0或C#4中使用'async' /'await'。这是C#5中的一项新功能,取决于.NET 4.5中的类型。 –
乔恩 - 因为他使用TaskEx.Run,我猜他正在使用异步定位包,它可以让你定位4.0并使用异步/等待 –