Cheng Chen
Cheng Chen

Reputation: 43523

Async property in c#

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.)

Upvotes: 7

Views: 25814

Answers (4)

Stephen Cleary
Stephen Cleary

Reputation: 456447

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;

Upvotes: 17

Euphoric
Euphoric

Reputation: 12849

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#?

Upvotes: 15

Filip Cordas
Filip Cordas

Reputation: 2561

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

Upvotes: 0

Vignesh.N
Vignesh.N

Reputation: 2666

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.

Upvotes: 4

Related Questions