Steven Trinh
Steven Trinh

Reputation: 9

How can I cancel a running OpenAsync() After Task.Wait() in .NET?

I want connect to DB through anytime Client click Button. When Client clicks button many time with different ConnectionString. Now I want to return only last Connection created by Client. Therefore, I must cancel last Task and created new Task. The Problem is how can I cancel a Task after I call Task.wait() use CancellationToken? Because when I not yet call wait(), Task Status will be WaitForActive, so I will never can receive result. Please help me solve that case. My draft code below:

    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();
        }
    }

Upvotes: 0

Views: 321

Answers (1)

sa-es-ir
sa-es-ir

Reputation: 5102

Don't use wait on tasks because of freeze main thread.

You can use a dictionary of tasks and cancellation tokens to manage your tasks like this(I just simulate your methods):

      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";
        }

Upvotes: 1

Related Questions