7

In my windows 8 application there is a global class where there are a few static properties like:

public class EnvironmentEx
{
     public static User CurrentUser { get; set; }
     //and some other static properties

     //notice this one
     public static StorageFolder AppRootFolder
     {
         get
         {
              return KnownFolders.DocumentsLibrary                    
               .CreateFolderAsync("theApp", CreationCollisionOption.OpenIfExists)
               .GetResults();
         }
     }
}

You can see I want to use the application root folder somewhere else in the project, so I make it a static property. Inside the getter, I need to make sure the root folder exists,otherwise create it. But the CreateFolderAsync is an async method, here I need a synchronized operation. I tried GetResults() but it throws an InvalidOperationException. What is the correct implementation? (The package.appmanifest is correctly configured, the folder is actually created.)

Servy
  • 202,030
  • 26
  • 332
  • 449
Cheng Chen
  • 42,509
  • 16
  • 113
  • 174

4 Answers4

16

I suggest you use asynchronous lazy initialization.

public static readonly AsyncLazy<StorageFolder> AppRootFolder =
    new AsyncLazy<StorageFolder>(() =>
    {
      return KnownFolders.DocumentsLibrary                    
          .CreateFolderAsync("theApp", CreationCollisionOption.OpenIfExists)
          .AsTask();
    });

You can then await it directly:

var rootFolder = await EnvironmentEx.AppRootFolder;
Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
14

Good solution: Don't make a property. Make an async method.

"I hate await, how can I make everything synchronous?" solution: How to call asynchronous method from synchronous method in C#?

peterh
  • 11,875
  • 18
  • 85
  • 108
Euphoric
  • 12,645
  • 1
  • 30
  • 44
4

use the await keyword

 public async static StorageFolder GetAppRootFolder() 
 { 
          return await ApplicationData
                      .LocalFolder
                      .CreateFolderAsync("folderName");
 } 

and in your code

var myRootFolder = await StaticClass.GetAppRootFolder(); // this is a synchronous call as we are calling await immediately and will return the StorageFolder.
Vignesh.N
  • 2,618
  • 2
  • 25
  • 33
0

Here is an idea.

public Task<int> Prop {
    get
    {
        Func<Task<int>> f = async () => 
        { 
            await Task.Delay(1000); return 0; 
        };
        return f();
    }
}

private async void Test() 
{
    await this.Prop;
}

but it creates a new Func object for every call this would do the same

public Task<int> Prop {
    get
    {
        return Task.Delay(1000).ContinueWith((task)=>0);
    }
}

You can't await a set since await a.Prop = 1; is not allowed

Maximilian Ast
  • 3,369
  • 12
  • 36
  • 47
Filip Cordas
  • 2,531
  • 1
  • 12
  • 23