6

I’m using MvvmCross and the AsyncEx library within a Windows 10 (UWP) App.

In a ViewModel, I have an INotifyTaskCompletion property (1) which is wired-up to an Async method in the ViewModel (2)

In (2), I call an Async library method which:

  • Checks a local cache
  • Downloads data asynchronously
  • Adds the data to the cache

The caching code cannot be made asynchronous and so the library method contains both blocking and asynchronous code.

Q. What’s the best way to prevent blocking the UI thread?

I understand from Stephen Cleary to not to block in asynchronous code and not use Task.Run in library methods. So do I have to….

Move the caching calls into (2) e.g.

  • Use Task.Run (to check the cache)
  • Call the library method asynchronously
  • Use Task.Run again (to cache the data)?

Is there a better way?

2
  • 1
    Have you some code you could share? Commented Mar 21, 2016 at 9:13
  • Depends on your definition of "better". If you can't change the cache code and want to use async/await, then using Task.Run() for the caching code is "correct". Commented Mar 21, 2016 at 9:13

1 Answer 1

8

If you have completely synchronous code which you can't change to make it return an awaitable, and want to make it asynchronous, then yes, your only choice if you want to use async/await is to use Task.Run().

Something like:

public async Task<T> MyMethod()
{
   T result = await Task.Run(() => CheckCacheOnSyncMethodICantChange());
   if(result != null)
   {
     result = await MyLibraryMethodThatReturnsATask();
     await Task.Run(() => AddToCacheOnSyncMethodICantChange(result));
   }
   return result;
}

Should be ok.

Sign up to request clarification or add additional context in comments.

5 Comments

Despite my answer, and for your specific case, a cache should be fast (that's the reason you use it)... Are you sure you need to make the cache methods asynchronous?
I'm using SQLite.net to cache the data in a file-based database. Because this work is non-CPU bound, I want to do it without blocking the UI thread. Have I missed something?
@Howard no, it's fine... as long as your library method takes significant more time than checking and adding to the cache. I'm not experienced with SQLite, but I recall having seen an SQLiteAsyncConnection somewhere if you are using SQLite.Net which had GetAsync and InsertAsync
I believe the SQLite.net async library methods are simply doing a Task.Run around the sync library methods, which is described as an anti-pattern (by some).
@Howard yes, actually, Task.Factory.StartNew, it seems: github.com/oysteinkrog/SQLite.Net-PCL/blob/master/src/… . Well, there's just no good solution. If your calling code (i.e., MyMethod in my answer) is a "caling method", and not a "library method" (and it should be, since you don't want your libraries to depend on an sqlite file database :-) ), then using Task.Run is just ok

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.