async/await - truly cancelling an await and series of await

Locked async/await - truly cancelling an await and series of await

  • lunes, 05 de marzo de 2012 9:38
     
     

    Hi,

    For one of the use case I would like to set textbox with some value when user presses a button

    void OnClick(yada yada)

    textBox.Text = await GetData();

    where GetData has a bunch of await calls

    async Task<String> GetData(){

    var x1 = await DoFunction1TaskAsync();

    var x2 await DoFunction2TaskAsync(x1);

    ...

    return somestring

    }

    1 - For my app, I do not disable the button when user clicks on it, this is so I can cancel the current operation if any, and start new operation). Question: when user hit the button reptitively, how can I truly and completely cancel the current running task such that old task's result is completely ignored (not updating the textbox text), before the next operation can continue.

    I know i can use cancellation token to cancel tasks but then isn't there a chance that before the cancellation is acknowledged, the operation completes thus also completing await, which in turn queues the textbox.text = <xxx> on the UI thread, all from the older task that was cancelled? basically I do not want intermediate text  on the textbox.

    2 - also if we cancel one await task, how can I cancel the following await so they do not execute? i.e. in the case above if we cancel DoFunction1TaskAsync() i do not want DoFunction2TaskAsync() to execute (and not trigger exception when updating the textbox text because of cancellatino).

    Maybe i do not understand task/cancellation well, but this would help me understand the intracacies.

    Thanks,

    Rohit







    • Editado RohitOn.Net lunes, 05 de marzo de 2012 11:42
    •  

Todas las respuestas

  • lunes, 05 de marzo de 2012 17:25
    Moderador
     
     Respondida

    1. You need to use a CancellationTokenSource here.  You would cancel the token source (on the running operation), then start the new one. This should prevent your old operation from completing (provided it's not already completed).

    "I know i can use cancellation token to cancel tasks but then isn't there a chance that before the cancellation is acknowledged, the operation completes thus also completing await, which in turn queues the textbox.text = <xxx> on the UI thread, all from the older task that was cancelled? "

    Not really - the issue is, if the other operation is completed, this will have already happened.  Since you have your button click event on the UI thread, it can't happen simultaneously with any other UI thread operation - so (provided you check for the CancellationToken.IsCancellationRequested flag or throw if a cancellation is requested) you will be in one of two states - the text box operation will have already completed, or the new one will get cancelled.

    2. You need to check your CancellationToken to see if cancellation has been requested before calling DoFunction2TaskAsync().  This lets you not call it.  You can throw or just return at this point - it's up to you and what makes the most sense in your scenario.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    • Marcado como respuesta RohitOn.Net martes, 06 de marzo de 2012 1:52
    •  
  • martes, 06 de marzo de 2012 1:53
     
     
    Thanks much.