0

I'm using the Google API with .NET library. I am building a Windows installed app, and want to allow the user to cancel if it is taking too long. Can anyone show me some sample C# code to cancel an Execute() or ExecuteAsync() call? I am running all the API communications in a separate thread. That API thread will check a global variable to see if it should stop, but if that separate thread is stuck on an Execute(), how can I stop it? I'm hoping there is a more elegant way that just calling Abort() on the thread. Here is some pseudo-code:

CancellationTokenSource tokenSource;
CalendarService cs;

private void Form1_Load(object sender, System.EventArgs e)
{
    // Create the thread object
    m_syncWorker = new SyncWorker();
    m_workerThread = new Thread(m_syncWorker.StartSync);

    // Create the Cancellation Token Source
    tokenSource = new CancellationTokenSource();

    // Start the worker thread.
    m_workerThread.Start();

    // Waits, and monitors thread...  If user presses Cancel, want to stop thread
    while(m_workerThread.IsAlive)
    {
        if(bUserPressedCancelButton) tokenSource.Cancel();
    }
}

public void StartSync()
{
    UserCredential credential;
    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
        new ClientSecrets
        {
            ClientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
            ClientSecret = "yyyyyyyyyyyyyyyyyyyyy"
        },
        new[] { CalendarService.Scope.Calendar },
        "johndoe@gmail.com",
        CancellationToken.None,
        new FileDataStore("Somefolder"));

    // Create the service
    cs = new CalendarService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential,
        ApplicationName = "My App",
    });

    // do some stuff...

    // wait for this to complete, or user cancel
    InsertAllEventsTask(e).Wait();
}

private async Task InsertAllEventsTask(Event e)
{
    try
    {
        // trying to cancel this...
        await cs.Events.Insert(e, "primary").ExecuteAsync(tokenSource.Token);
    }
    catch (TaskCanceledException ex)
    {
        // handle user cancelling
        throw ex;
    }
}
Mark
  • 440
  • 4
  • 16

1 Answers1

1

If you want to cancel an operation in the middle, you should use the async version, ExecuteAsync.

ExecuteAsync gets a cancelation token, so you can create a CancellationTokenSource, as described here: http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx and cancel the operation in the middle.

Your code will look something like:

var tokenSource = new CancellationTokenSource();
cs.Events.Insert(e, "primary").ExecuteAsync(tokenSource).
     ContinueWith( .... whatever you wish to continue with .... )
....
tokenSource.Cancel();
peleyal
  • 3,472
  • 1
  • 14
  • 25
  • Thanks peleyal, but I couldn't make this work. I modified my original question to show how I implemented your answer. I must be doing something wrong. When ExecuteAsync() is taking a long time I issue tokenSource.Cancel(), but that doesn't cancel the ExecuteAsync(). It still stays stuck on ExecuteAsync() until some long timeout, when it eventually throws its own TaskCanceledException. I am not trying to execute other code while ExecuteAsync() is running. I want to wait for it to complete or be cancelled. – Mark Oct 26 '14 at 16:26
  • what is the timeout? How long are you stuck? Why don't you use Task.Factory.StartNew (http://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx) it will make your life easier by the way – peleyal Oct 27 '14 at 22:28
  • The timeout is like 1 or 2 minutes... Calling tokenSource.Cancel() makes no noticeable difference in how long it takes for that method to return. Is Task.Factory.StartNew going to improve my ability to cancel the ExecuteAsyn() call? I'm migrating code from an old project. I'm trying to change as little as possible, mostly only stuff related to the Google API v3. – Mark Oct 27 '14 at 23:10
  • Which version of the library do you use? Is it this one - https://www.nuget.org/packages/Google.Apis.Calendar.v3/? – peleyal Oct 28 '14 at 13:21
  • Yes, that is it. Version 1.9.0.103. – Mark Oct 28 '14 at 17:10
  • It sounds really weird, it should not BLOCK you for more than 1-2 seconds the most. Did you change the default exponential back-off behavior? Can you also attach the code where you create the CalendarService? – peleyal Oct 29 '14 at 19:24
  • I've updated the code to show how I create the CalendarService. I do not change the exponential backoff from the default. Once in a while the ExecuteAsync() can get stuck for a while (1-2 minutes), I assume doing exponential backoff, or waiting on the server somehow. This is what I'd like to be able to cancel in a reasonably quick manner. For testing I am doing a lot of Insert() until it gets stuck, and then doing tokenSource.Cancel(), but it still doesn't return any sooner than the 1-2 minute timeout. – Mark Oct 29 '14 at 22:34