I’m currently trying to port a fair amount of existing synchronous code to WinRT.
As part of this, I’m hitting problems with the existing code expecting some operations to be synchronous – e.g. for file I/O
To adapt this existing code to work with the IAsyncOperation style API within WinRT, I’ve used a technique of wrapping the IAsyncOperation with an extension method like:
namespace Cirrious.MvvmCross.Plugins.File.WinRT
{
public static class WinRTExtensionMethods
{
public static TResult Await<TResult>(this IAsyncOperation<TResult> operation)
{
var task = operation.AsTask();
task.Wait();
if (task.Exception != null)
{
// TODO - is this correct?
throw task.Exception.InnerException;
}
return task.Result;
}
}
}
from MvvmCross WinRT ExtensionMethods – with a similar method for IAsyncAction
These wrappers seems to work – and they allow me to use the Async methods in synchronous code like:
public IEnumerable<string> GetFilesIn(string folderPath)
{
var folder = StorageFolder.GetFolderFromPathAsync(ToFullPath(folderPath)).Await();
var files = folder.GetFilesAsync().Await();
return files.Select(x => x.Name);
}
I understand that this isn’t really in the spirit of WinRT; but I am expecting these methods to normally only get called on background threads in the first place; and I am writing this with the goal of making my code cross-platform compatible – including to platforms which don’t yet support await-async and/or to developers who aren’t yet ready to make the jump.
So… the question is: what risks am I running by using this type of code?
And as a second question, is there any better way I could achieve code reuse for areas such as File I/O?
I’m finally going to answer this….
And the answer is you can’t really do it.
Even if you try to use some of the cleaner methods suggested in the other answers, then you still ultimately hit exceptions if you try to run the code on any thread which has promised not to block – e.g. if you try to run on the UI thread or on a threadpool thread.
So… the answer is you simply have to rearchitect that legacy code so that it’s in some way asynchronous!