6

データテーブルを返すメソッドがあります。.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];
}
4

3 に答える 3

10

まず、 .NET 4またはC#4ではasync/を使用できません。これはC#5の新機能です。.NET4の上にインストールされたCTPがありましたが、それらのCTPには明確なバグがあります。使用しないでください。 。C#5コンパイラを含む.NET4.5のフルリリースバージョンを使用する必要があります。(これはすべてVisual Studio 2012にあります。)await

次に、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);
}

タスクを開始してすぐに待機する場合は、メソッドを同期的に呼び出すこともできます。

于 2012-09-26T06:00:55.253 に答える
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;
    }
于 2014-06-25T03:02:28.623 に答える
3

asyncコードを使用する場合は、ブロックしないでください。また、 AsyncCTPではなくAsyncTargetingPackを使用していることを確認してください。

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);
}
于 2012-09-26T13:22:43.517 に答える