我正在玩任务,而且我不知道如何在抛出异常时取消任务。我正在尝试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();
}
}
}
答案 0 :(得分:4)
cancellation分为两部分:请求取消(TaskCompletionSource.SetCanceled
)并回复该取消请求。
当发生异常时,您的代码正在调用SetCanceled
,如果您希望在 一个异常时取消其他操作,则可以。
但是,代码中没有任何内容正在侦听取消令牌。它应该传递给支持CancellationToken
的API,或者定期检查(CancellationToken.ThrowIfCancellationRequested
),或者附加一个取消回调(CancellationToken.Register
)。否则,它只是一个设置的标志,没有人检查它。