2015-02-16 4 views
0

я делаю что-то для окна Маркет, что это проект Универсального приложения, и я отладка на 8,1 ноутбуке Windows, и окно 8,1 Surface Pro 3.странного поведение в StorageFolder.CreateFolderAsync

Я пытаясь создать некоторые вложенные папки в ApplicationData.Current.LocalFolder. Из конструктора главного экрана, я называю

CacheManager.InitializeOfflineFiles().Wait(); 

и код для CacheManager.InitializeOfflineFiles() является

public static async Task InitializeOfflineFiles() 
{ 
    try 
    { 
     StorageFolder s1 = await ApplicationData.Current.LocalFolder.CreateFolderAsync("one", CreationCollisionOption.OpenIfExists); 
     Debug.WriteLine("Created folder one"); 
     StorageFolder s2 = await s1.CreateFolderAsync("two", CreationCollisionOption.OpenIfExists); 
     Debug.WriteLine("Created folder two"); 
     StorageFolder s3 = await s2.CreateFolderAsync("three", CreationCollisionOption.OpenIfExists); 
     Debug.WriteLine("Created folder three"); 
     StorageFolder s4 = await s3.CreateFolderAsync("four", CreationCollisionOption.OpenIfExists); 
     Debug.WriteLine("Created folder four"); 
    } 
    catch (Exception e) 
    { 
     Debug.WriteLine("Windows doesn't love you. Exception: " + e.Message); 
    } 
} 

Когда я отладки это, не пройти создания папки «два ». Исключение не зарегистрировано, ничего нет. Кроме того, когда я запускаю это без отладки (Ctrl + F5), тот же результат, создается только dir «one/two» в локальном хранилище.

Это случай неправильного программирования async?

ответ

1

Это:

CacheManager.InitializeOfflineFiles().Wait(); 

вызывает приложение к тупиковой. Вот почему вы видите «повешение». Похоже, что вы, похоже, видите папку 1 & 2, так как я предполагаю, что это должно зайти в тупик, когда выполняется первый await.

Именно по этой причине вы shouldn't block on async code.

Поскольку конструкторы не могут быть асинхронными, используйте «Инициализировать Pattern» (or other known async initalization patterns) вместо того, чтобы выполнить свой код асинхронного:

public Task InitializeAsync() 
{ 
    return InitializeOfflineFilesAsync() 
} 

А из вашего кода, называют это от метода async контекста, возможно, обработчик события:

public async void SomeButtonClickEventHandler() 
{ 
    await InitializeAsync(); 
} 

Мораль рассказа, не называйте асинхронных методов с помощью вашего конструктора.

+0

Я думал о т его, но тогда, почему он не зашел в тупик по первым вызовам «CreateFolderAsync», но только на третьем? –

+0

@ThomasLevesque Я знаю, это странно. У нас определенно отсутствуют некоторые данные. Я не вижу другой причины, почему это должно висеть, но я не могу объяснить, что висит только после второго 'ожидания '. –

+0

Благодарим вас за ответ. Я признаю, что я ничего не знаю об этом API окон, что очевидно из моего вопроса о нообале, но действительно сложно разобраться в этом тупике.В Java вам нужно много работать для тупика, здесь ОС делает это за вас. Я действительно хотел иметь синхронный блок инициализации, но они не предоставляют никаких методов синхронизации для хранения. Это действительно глупо. –

1

Оказывается, я могу вызвать метод async из конструктора. В конструкторе:

var task = Task.Run(async() => 
    { 
     return await CacheManagerInitializeOfflineFiles(); 
    }); 
    string dummy = task.Result; 

метод в одном классе, вызывая метод асинхронной, который создает каталоги для хранения:

private async Task<string> CacheManagerInitializeOfflineFiles() 
{ 
    await CacheManager.InitializeOfflineFiles(); 
    return "done"; 
} 

Я действительно не хочу, чтобы поставить кнопку «инициализировать приложение», что будет быть плохой дизайн :)

0

Чтобы избежать тупиков, попробуйте следующее:

StorageFolder s1 = await ApplicationData.Current.LocalFolder.CreateFolderAsync("one", CreationCollisionOption.OpenIfExists).AsTask().ConfigureAwait(false);