1

We have a long established, greatly multiplatform codebase that is currently being ported to WinRT. One of the challenges we're facing is how to handle WinRT's asynchronous style.

For example, we are unsure how to handle WinRT's async file operations. Unsurprisingly, our codebase's API is synchronous. A typical example is our File::Open function which attempts to open a file and return with success or failure. How can we call WinRT functions and yet keep the behavior of our functions the same?

Note that we are unfortunately constrained by legacy: we cannot simply go and change the API to become asynchronous.

Thanks!

djcouchycouch
  • 12,724
  • 13
  • 69
  • 108
  • Seriously ponder Stephen Toub's [Should I Expose Synchronous Wrappers for Asynchronous Methods?](http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx) - it's a classic. – Stephen Cleary Oct 10 '12 at 17:19

2 Answers2

6

I assume you wish to reimplement the library to support WinRT apps while not changin the definitions of the APIs so that existing applications remain compatible.

I think that if you don't include the await keyword when calling an async method you will not do an async operation, it should execute in a synchronous way. But it really doesn't work if the method returns a value (in my experience).

I've been using this code to make a file operation synchronous:

IAsyncOperation<string> contentAsync = FileIO.ReadTextAsync(file);
contentAsync.AsTask().Wait();
string content = contentAsync.GetResults();
Mattias Lindberg
  • 2,064
  • 3
  • 24
  • 34
  • 1
    Note that in many situations this might lead to a deadlock since the operation that you are waiting for might require an event to be processed on the thread you are waiting on and thus blocking the event from being processed. – Filip Skakun Oct 10 '12 at 16:46
  • Then what other pattern is there to make async calls sync? In my app I want to ensure that I read this config information before the app show the initial screen, so I'll have to wait somewhere for this code to complete... @FilipSkakun – Mattias Lindberg Oct 11 '12 at 06:44
  • 1
    @MattiasLindberg Use `ConfigureAwait(false);` instead of `Wait()` so it will get executed in a background thread. – Manuel Rauber Oct 11 '12 at 09:04
2

If you want to share your code with a platform that does not support async/await - you are probably better off having a different API for the old platform and the new one with switches like

#if SILVERLIGHT
#elif NETFX_CORE
#elif WPF
#endif

Eventually the async APIs are likely to show up in older platforms and you could actually wrap the non-async calls into Tasks to make them async if they don't. Forcing async method to work synchronously is bound to bite you back rather quickly. Your WinRT app might become unresponsive for a few seconds for example and get killed by the OS. Or you could get deadlocks waiting for tasks to complete and blocking the thread they try to complete on.

Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
  • Probably better off, but not possible. The API, as I mentioned in the post, is old and pretty much set in stone. An application built upon the codebase is expected to build and work with no or almost no changes. As for responsiveness, the main application code is run in a separate thread anyway, so UI is not affected. – djcouchycouch Oct 10 '12 at 18:40
  • Can't edit the original comment: an application built upon the codebase is expected to build and work on a different platform with no or almost no changes. – djcouchycouch Oct 10 '12 at 18:47