0

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();
        }
    }
4
  • 1
    You should not use _result.Wait() - this blocks the thread and thus the user will never be able to click the button - your whole app is frozen Commented Apr 10, 2021 at 4:15
  • @torvin thanks. I know that. await Task will same Wait() because my task will never start when await or wait() has been called. Commented Apr 10, 2021 at 4:24
  • You use WinForm or web app? Commented Apr 10, 2021 at 5:25
  • @Saeed Winform. Can u have any idea? Commented Apr 10, 2021 at 6:06

1 Answer 1

1

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";
        }
Sign up to request clarification or add additional context in comments.

5 Comments

I can see you have a condition that is !item.Key.IsCompleted && !item.Value.IsCancellationRequested and call cancel() method for cancel.So, where is Cancel() method bro? and If !item.Value.IsCancellationRequested is true, maybe I will don't want to kill last task.
@StevenTrinh With fire cancellation token you can end a task. when you call Cancel method from CancellationTokenSource you cancel that task and no need for extra cancel method. for that If when item.Key.IsCompleted is true means your task already done and can not cancel it and when item.Value.IsCancellationRequested is true means task is already cancelled and no need to cancel it.
@StevenTrinh Have you test this answer? Is it ok?
Already check it. Have a problem here. That is when OpenAsync() run. It will check CancellationToken first then call Open() method for connecting. So, later, I call Cancel() but it will not cancel OpenAsync() because it already step out of that check cancellationtoken section.
@StevenTrinh No if cancellation token fires during run task it will cancelled the task. your question is to cancel all task that in queue before new incoming task and this solution do this, I think.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.