使用异步 .net 4.0 返回数据表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12595119/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 16:38:02  来源:igfitidea点击:

Return DataTable using async .net 4.0

.netc#-4.0async-await

提问by Malcolm

I have a method that returns a datatable. I thought using .net 4.0 I could just async logic and return data. But this code returns null Datatable object. Any ideas what is wrong with this code.

我有一个返回数据表的方法。我认为使用 .net 4.0 我可以只是异步逻辑并返回数据。但此代码返回空数据表对象。任何想法这段代码有什么问题。

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];
}

回答by Jon Skeet

Firstly, you can't use async/ awaitwith .NET 4 or C# 4. It's a new feature in C# 5. There were CTPs which installed on top of .NET 4, but there are definite bugs in those CTPs - don'tuse them. You should use the full release version of .NET 4.5, which includes the C# 5 compiler. (All this is in Visual Studio 2012.)

首先,您不能在 .NET 4 或 C# 4 中使用async/ await。这是 C# 5 中的一个新功能。有安装在 .NET 4 之上的 CTP,但这些 CTP 中存在明确的错误 -不要使用它们. 您应该使用 .NET 4.5 的完整发行版,其中包括 C# 5 编译器。(所有这些都在 Visual Studio 2012 中。)

Secondly, you're using the wrong property of the task, as Cuong Le showed. The Resultproperty is how you get at the result of a Task<T>.

其次,正如 Cuong Le 所示,您使用了错误的任务属性。该Result属性是您获得 a 的结果的方式Task<T>

Thirdly, after making the change to use the Resultproperty, you'd be blocking for the table to be fetched - making it pointless. This:

第三,在更改使用该Result属性后,您将阻塞要获取的表 - 使其毫无意义。这个:

public DataTable GetData(string sql, string connectionName)
{
    DataTable dt = (DataTable)GetDataAsync(sql, connectionName).Result;
    return dt;
}

... is largely equivalent to:

...在很大程度上等同于:

public DataTable GetData(string sql, string connectionName)
{
    return FillData(sql, connectionName);
}

If you're going to start a task and immediately wait on it, you might as well just call the method synchronously.

如果您要启动一个任务并立即等待它,您不妨同步调用该方法。

回答by Kim Ki Won

My own source code.

我自己的源代码。

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;
    }

回答by Stephen Cleary

If you want to use asynccode, then don't block on it. Also, make sure you're using the Async Targeting Packand not an Async CTP.

如果你想使用async代码,那么不要阻塞它。此外,请确保您使用的是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);
}