C# 如何在.NET中Task.Wait()之后取消正在运行的OpenAsync()?
我想通过anytime Client click按钮连接到DB。当客户端使用不同的ConnectionString多次单击按钮时。现在我只想返回客户端创建的最后一个连接。因此,我必须取消上一个任务并创建新任务。问题是调用Task.wait()后如何取消任务?使用CancellationToken?因为当我还没有调用C# 如何在.NET中Task.Wait()之后取消正在运行的OpenAsync()?,c#,.net,task,kill,cancellationtokensource,C#,.net,Task,Kill,Cancellationtokensource,我想通过anytime Client click按钮连接到DB。当客户端使用不同的ConnectionString多次单击按钮时。现在我只想返回客户端创建的最后一个连接。因此,我必须取消上一个任务并创建新任务。问题是调用Task.wait()后如何取消任务?使用CancellationToken?因为当我还没有调用wait()时,任务状态将是WaitForActive,所以我将永远无法收到结果。请帮我解决那个案子。我的代码草案如下: private SqlConnection _conn
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 SqlConnection\u connection=null;
private CancellationTokenSource _source=null;
私有任务_result=null;
公共任务GetStatusAsync(字符串连接字符串)
{
如果(_source==null)
_source=新的CancellationTokenSource();
if(_connection!=null&&u connection.State==ConnectionState.Connecting)
{
_source.Cancel();
_source=新的CancellationTokenSource();
}
_结果=ConnectDatabaseAsync(connectionString.Trim(),_source.Token);
_result.Wait();
返回结果;
}
专用异步任务ConnectDatabaseAsync(字符串连接字符串,CancellationToken CancellationToken)
{
if(_connection==null)
_connection=newsqlconnection();
尝试
{
_connection.ConnectionString=ConnectionString;
wait\u connection.OpenAsync(cancellationToken);
返回“ok”;
}
捕获(例外情况除外)
{
返回ex.消息;
}
最后
{
if(_connection.State==ConnectionState.Open)
_connection.Close();
}
}
由于冻结主线程,所以不要使用等待任务
您可以使用任务和取消令牌的字典来像这样管理您的任务(我只是模拟您的方法):
private static readonly Dictionary Tasks=new Dictionary();
公共异步任务GetStatusAsync()
{
var source=新的CancellationTokenSource();
var task=ConnectDatabaseAsync(“YourConnection”,source.Token);
if(Tasks.Any())
foreach(任务中的变量项)
{
如果(!item.Key.IsCompleted&!item.Value.IsCancellationRequested)
item.Value.Cancel();
}
任务。添加(任务、源);
等待任务;
返回任务。结果;
}
专用异步任务ConnectDatabaseAsync(字符串连接、CancellationToken令牌)
{
等待任务。延迟(10000,令牌);
返回“Ok”;
}
您不应该使用\u result.Wait()
-这会阻止线程,因此用户将永远无法单击该按钮-您的整个应用程序将被禁用frozen@torvin谢谢我知道。Wait任务将使用相同的Wait(),因为调用Wait或Wait()后,我的任务将永远不会启动。您使用WinForm或web app?@Saeed WinForm。你知道吗?我可以看出你有一个条件是!item.Key.IsCompleted&!item.Value.IsCancellationRequested
并调用cancel()
方法进行取消。那么,cancel()方法bro在哪里?如果!item.Value.IsCancellationRequested为true,可能我不想终止最后一个任务。@Steventrin使用fire取消令牌可以结束任务。当您从CancellationTokenSource
调用Cancel
方法时,您将取消该任务,并且不需要额外的Cancel方法。对于该If
whenitem.Key.IsCompleted
为true表示任务已完成且无法取消,whenitem.Value.IsCancellationRequested
为true表示任务已取消且无需取消。@Steventrin您测试过这个答案吗?可以吗?已经检查过了。这里有个问题。这就是OpenAsync()运行的时间。它将首先检查CancellationToken,然后调用Open()方法进行连接。因此,稍后,我调用Cancel(),但它不会取消OpenAsync(),因为它已跳出check cancellationtoken部分。@StevenTrinh否如果在运行任务期间触发取消标记,它将取消该任务。我认为,你们的问题是在新的传入任务之前取消队列中的所有任务,这个解决方案就是这样做的。
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";
}