使用async .net 4.0返回DataTable

Mal*_*olm 5 .net async-await c#-4.0

我有一个返回数据表的方法.我以为使用.net 4.0我可以只是异步逻辑并返回数据.但是这段代码返回null 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];
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 9

首先,你不能使用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;
}
Run Code Online (Sandbox Code Playgroud)

......在很大程度上相当于:

public DataTable GetData(string sql, string connectionName)
{
    return FillData(sql, connectionName);
}
Run Code Online (Sandbox Code Playgroud)

如果您要启动任务并立即等待它,您也可以同步调用该方法.


Kim*_*Won 8

我自己的源代码.

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;
    }
Run Code Online (Sandbox Code Playgroud)