mardi 4 août 2015

C# return before await - without starting a new Task

This is for an iOS app written in Xamarin. All my application code runs in the main thread (i.e. the UI thread).

The UI code does something as follows:

public async void ButtonClicked()
{
    StartSpinner();
    var data = await UpdateData();
    StopSpinner();
    UpdateScreen(data);
}

The UpdateData function does something as follows:

public Task<Data> UpdateData()
{
   var data = await FetchFromServer();
   TriggerCacheUpdate();
   return data;
}

TriggerCacheUpdate ends up calling the following function defined below

public Task RefreshCache()
{
    var data = await FetchMoreDataFromServer();
    UpdateInternalDataStructures();
}

My question is how should TriggerCacheUpdate be written? The requirements are:

  1. Can't be async, I don't want UpdateData and consequently ButtonClicked to wait for RefreshCache to complete before continuing.
  2. UpdateInternalDataStructures needs to execute on the main (UI) thread, i.e. the thread that all the other code shown above executes on.

Here are a few alternatives I came up with:

public void TriggerCacheUpdate()
{
    RefreshCache();
}

The above works but generates a compiler warning. Moreover exception handling from RefreshCache doesn't work.

public void TriggerCacheUpdate()
{
    Task.Run(async() =>
    {
        await RefreshCache();
    });
}

The above violates requirement 2 as UpdateInternalDataStructures is not executed on the same thread as everything else.

A possible alternative that I believe works is:

private event EventHandler Done; 
public void TriggerCacheUpdate()
{
    this.task = RefreshCache();
    Done += async(sender, e) => await this.task;
}

Task RefreshCache() {
    var data = await FetchMoreDataFromServer();
    UpdateInternalDataStructures();
    if (Done != null) {
       Done(this, EventArgs.Empty);
    }
}

Does the above work? I haven't ran into any problems thus far with my limited testing. Is there a better way to write TriggerCacheUpdate?

Aucun commentaire:

Enregistrer un commentaire