问题描述
我想随时通过客户端单击按钮连接到数据库。当客户端使用不同的 ConnectionString 多次单击按钮时。现在我只想返回客户端创建的最后一个连接。因此,我必须取消上一个任务并创建新任务。问题是如何在调用 Task.wait() 使用 CancellationToken 后取消任务?因为当我还没有调用wait()
时,任务状态将是WaitForActive,所以我永远无法收到结果。请帮我解决那个案子。我的草稿代码如下:
private sqlConnection _connection = null;
private CancellationTokenSource _source = null;
private Task<string> _result = null;
public Task<string> GetStatusAsync(string connectionString)
{
if (_source == null)
_source = new CancellationTokenSource();
if (_connection != null && _connection.State == ConnectionState.Connecting)
{
_source.Cancel();
_source = new CancellationTokenSource();
}
_result = ConnectDatabaseAsync(connectionString.Trim(),_source.Token);
_result.Wait();
return _result;
}
private async Task<string> ConnectDatabaseAsync(string connectionString,CancellationToken cancellationToken)
{
if (_connection == null)
_connection = new sqlConnection();
try
{
_connection.ConnectionString = connectionString;
await _connection.OpenAsync(cancellationToken);
return "ok";
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
if (_connection.State == ConnectionState.Open)
_connection.Close();
}
}
解决方法
不要使用等待任务,因为冻结主线程。
你可以使用任务字典和取消令牌来管理你的任务(我只是模拟你的方法):
private static readonly Dictionary<Task,CancellationTokenSource> Tasks = new Dictionary<Task,CancellationTokenSource>();
public async Task<string> GetStatusAsync()
{
var source = new CancellationTokenSource();
var task = ConnectDatabaseAsync("YourConnection",source.Token);
if (Tasks.Any())
foreach (var item in Tasks)
{
if (!item.Key.IsCompleted && !item.Value.IsCancellationRequested)
item.Value.Cancel();
}
Tasks.Add(task,source);
await task;
return task.Result;
}
private async Task<string> ConnectDatabaseAsync(string connection,CancellationToken token)
{
await Task.Delay(10000,token);
return "Ok";
}