Why file async API block

I am writing a simple metro application. However, when accessing files, the API is blocked. By blocking, I mean that programs wait forever. Creating / opening a file or folder should take no more than a few seconds. In this case, it lasts forever.

When I run the program, it never returns from OnTest. This is what you get. I understand. Wait until the creation of files and folders is complete. Maybe this is not a great design. However, this is not the point.

My question is:

  • You get the same behavior (blocks the program forever)
  • Is this what is supposed to happen, or is it a bug in WinRT? (I use consumer preview)
  • If this is the expected behavior, why does this happen forever?

Here is the XAML code:

<Button Click="OnTest">Test</Button>

Here is the C # code:

 private async void OnTest(object sender, RoutedEventArgs e)
        {
            var t = new Cache("test1");
            t = new Cache("test2");
            t = new Cache("test3");
        }
        class Cache
        {
            public Cache(string name)
            {
                TestRetrieve(name).Wait();
            }
            public static async Task TestRetrieve(string name) 
            {
                StorageFolder rootFolder = ApplicationData.Current.LocalFolder;
                var _folder = await rootFolder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists);
                var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
            }
        }

Cache ( "test2" );

+3
4

, , .

, :

  • .
  • , , .
  • .
  • .
  • .

. ?

; , , , , . , , , . , , , , "" .

, .

.

, , .

, . ? :

void M()
{
    Task tx = GetATask();
    tx.Wait();
}
async Task GetATask()
{
    Task ty = DoFileSystemThingAsync();
    await ty;
    DoSomethingElse();
}

-: ? - , (1) , (2) : , .

, GetATask. ? , , , . " -, ".

? ? DoSomethingElse. , , , , DoSomethingElse , .

, - , GetATask . ? , , . - , , , GetATask.

? ! GetATask.

, . . " ". , . - DoSomething. , " GetATask". DoSomethingElse.

: , - . , - , : ", -, , . , DoSomethingElse".

. ? , GetATask, DoSomethingElse, . , DoSomethingElse, , DoSomethingElse.

? , , DoSomethingElse , , ", DoSomethingElse" , ! , , , , , , , .

Calling Wait , , - , . Wait . ; , " " " ". .

+15

Wait() Cache. , .

. . , factory :

public class Cache
{
    private string cacheName;

    private Cache(string cacheName)
    {
        this.cacheName = cacheName;
    }

    public static async Cache GetCacheAsync(string cacheName)
    {
         Cache cache = new Cache(cacheName);

         await cache.Initialize();

         return cache;
    }

    private async void Initialize()    
    {   
            StorageFolder rootFolder = ApplicationData.Current.LocalFolder;   
            var _folder = await rootFolder.CreateFolderAsync(this.cacheName, CreationCollisionOption.OpenIfExists);   
            var file = await _folder.CreateFileAsync("test.xml", CreationCollisionOption.OpenIfExists);
   }
}

:

await Task.WhenAll(Cache.GetCacheAsync("cache1"), Cache.GetCacheAsync("cache2"), Cache.GetCacheAsync("cache3"));   
+7
TestRetrieve(name).Wait();

, , .Wait().

.Wait(), .

+1

, , , " ", . , .

async/await, , async, "" . , "". - , . ( ... , )

, async context paramater, . "wait", ( !).

- TestRetrieve (name).Wait(); , , , . async-activity-wait . UI-, OnTest. :

:

UI-Thread ->
    OnTest

/ , "" TestRetrieve async UI-Thread. , , , "" UIThread, .

async async/await ( UI-) , . , . , TestRetrieve . "Wait" ...

await (new Cache("test1")).TestRetrieve("test1");

When you do this, the TestRetrieve asynchronous context is correctly bound, so the chain looks like this:

UI-Thread ->
    OnTest ->
        TestRetrieve

Now the asynchronous UI thread loop handler can resume TestRetrieve during asynchronous terminations, and your code will work as expected.

If you want to create an “async constructor,” you need to do something like the Drew GetCacheAsync template, where you create a static Async method that builds the object synchronously and then expects the async method. This creates the correct async chain, waiting and “binding” the context to the end.

0
source

All Articles