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
  • 197,813
  • 25
  • 319
  • 428
Cheng Chen
  • 41,149
  • 16
  • 109
  • 168

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;
Stephen Cleary
  • 406,130
  • 70
  • 637
  • 767
13

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
  • 1
  • 15
  • 76
  • 99
Euphoric
  • 12,302
  • 1
  • 27
  • 41
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,541
  • 2
  • 25
  • 32
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,240
  • 12
  • 39
  • 46
Filip Cordas
  • 2,464
  • 1
  • 13
  • 23