【问题标题】:Cancel Task in await取消等待中的任务
【发布时间】:2017-10-25 05:51:42
【问题描述】:

我正在玩任务,当抛出异常时我不知道如何取消任务。我正在尝试使用TaskCompletionSourcecancel,但它不起作用。

有没有办法在抛出异常时完全停止任务?

public async Task Migrate()
{
    var tcs = new TaskCompletionSource<bool>();
    if (IsDataMigratorItemParameteresCorrect())
    {
        try
        {
            using (SqlConnection srcconnection = this.SourceConnection)
            {
                await srcconnection.OpenAsync();
                using (SqlCommand srccmd = CreateMigrateTaskCommand(this.SourceForHash, srcconnection))
                {
                    using (SqlDataReader srcreader = await srccmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
                    {
                        using (SqlConnection destconnection = this.DestinationConnection)
                        {
                           await destconnection.OpenAsync();

                           await CreateStageTable(destconnection, srcreader);
                           await BulkCopy(destconnection, srcreader);
                           await Merge(destconnection, srcreader);
                           await DropTable(destconnection); 
                        }
                    }
                }

            }
        }

        catch (Exception ex)
        {
            Console.WriteLine(DestinationCommand + " canceled\nException : " + ex.Message);
            tcs.SetCanceled();
        }
    }
}

private SqlCommand CreateMigrateTaskCommand(string commandQuery, SqlConnection connection)
{
    SqlCommand scmd = new SqlCommand(commandQuery, connection);
    return scmd;
}

private async Task Merge(SqlConnection conn, SqlDataReader reader)
{
    using (SqlCommand cmdMerge = conn.CreateCommand())
    {
        string mergeQuery = SqlGenerator.BuildMergeQuery(reader, DestinationCommand, this.SourceUniqueKey, this.DestinationUniqueKey);

        cmdMerge.CommandText = mergeQuery;
        cmdMerge.CommandType = CommandType.Text;
        cmdMerge.CommandTimeout = 0;
        await cmdMerge.ExecuteNonQueryAsync();
        Console.WriteLine("{0} - MERGE START\n", DestinationCommand);
    }
    Console.WriteLine("{0} - MERGE SUCCESS!\n", DestinationCommand);
}

private async Task BulkCopy(SqlConnection conn, SqlDataReader reader)
{
    using (SqlBulkCopy bcp = new SqlBulkCopy(conn.ConnectionString, SqlBulkCopyOptions.TableLock)) //table lock
    {
        bcp.SqlRowsCopied += bcp_SqlRowsCopied;
        bcp.BatchSize = this.BatchSize;
        bcp.EnableStreaming = true;
        bcp.BulkCopyTimeout = 0;
        bcp.NotifyAfter = 1000;

        string destTable = this.DestinationCommand + "_stage";
        bcp.DestinationTableName = destTable;

        await bcp.WriteToServerAsync(reader);
    }
}

private async Task CreateStageTable(SqlConnection conn, SqlDataReader reader)
{
    using (SqlCommand cmdCreateTable = conn.CreateCommand())
    {
        try
        {
            string createTableQuery = SqlGenerator.BuildCreateTableQuery(reader, this.DestinationCommand);

            cmdCreateTable.CommandText = createTableQuery;
            cmdCreateTable.CommandType = CommandType.Text;

            await cmdCreateTable.ExecuteNonQueryAsync();
            Console.WriteLine(this.DestinationCommand + " created!");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

private async Task DropTable(SqlConnection conn)
{
    using (SqlCommand cmdCreateTable = conn.CreateCommand())
    {
        try
        {
            string tableName = DestinationCommand + "_stage";
            var builder = new SqlCommandBuilder();
            string escapedTableName = builder.QuoteIdentifier(tableName);
            cmdCreateTable.CommandText = "drop table " + escapedTableName;
            Console.WriteLine(escapedTableName + " created!");
        }
        catch (Exception ex)
        {
            Console.WriteLine(DestinationCommand + " canceled\nException : " + ex.Message);
            tcs.SetCanceled();
        }
    }
}

【问题讨论】:

  • 您的代码示例不完整。
  • 我的错。现在编辑:)

标签: c# asynchronous async-await task cancellation


【解决方案1】:

cancellation 有两个部分:请求取消 (TaskCompletionSource.SetCanceled) 和响应取消请求。

您的代码在发生异常时调用SetCanceled,如果您想在那个发生异常时取消其他操作,这是可以的。

但是,代码中没有任何内容在监听取消令牌。它应该传递给支持CancellationToken 的 API,或者定期检查 (CancellationToken.ThrowIfCancellationRequested),或者附加一个取消回调 (CancellationToken.Register)。否则,它只是一个设置的标志,没有人检查它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多