2016-09-07 3 views
0

У меня есть окно, в котором используются некоторые методы async. Тем не менее, он висит только пользовательский интерфейс (во время этих операций) только тогда, когда я создать его во время выполнения, как это:Async метод зависает UI

private void button_Click(object sender, RibbonControlEventArgs e) 
{ 
    AboutWindow SettingsWindow = new AboutWindow(); 
    SettingsWindow.ShowDialog(); 
} 

Однако, если я создаю его так:

private AboutWindow SettingsWindow = new AboutWindow(); 
private void button_Click(object sender, RibbonControlEventArgs e) 
{ 
    SettingsWindow.ShowDialog(); 
} 

Все, кажется, будет хорошо и пользовательский интерфейс не висит.

Методы, внутри окна, которые вызывают проблемы, представлены ниже:

private async void CallUpdateDownload() 
{ 
    UpdaterStatus.CurrentUpdateStatus = await DownloadAndSaveInstallerAsync(UpdaterStatus.freshVersion); 
} 

public static async Task<UpdateStatus> DownloadAndSaveInstallerAsync(string NewVersion) 

Основное зависание происходит на этой строке внутри DownloadAndSaveInstallerAsync:

CloudBlockBlob blob = new CloudBlockBlob(new Uri(sas)); 
MemoryStream msRead = new MemoryStream(); 
blob.DownloadToStream(msRead); // HANGS HERE 

Вопросом является, почему это происходит? Почему создание окна при запуске предотвращает его зависание от асинхронных методов.

Другой вопрос:, что у меня есть другой объект, который также использует метод DownloadAndSaveInstallerAsync. Эти объекты создаются во время выполнения, и я не могу ничего сделать, чтобы предотвратить это зависание, возникающее при загрузке.

Как я могу предотвратить зависание пользовательского интерфейса в этой ситуации (создание объектов во время выполнения)?

Больше код ниже:

 private async void CallUpdateDownload() 
       { 
        UpdaterStatus.CurrentUpdateStatus = await UpdaterLogic.DownloadAndSaveInstallerAsync(UpdaterStatus.freshVersion); 
       } 

UpdaterLogic:

 public static async Task<UpdateStatus> DownloadAndSaveInstallerAsync(string NewVersion) 
       { 
     //... 
          if (await SaveInstallerToMemoryAsync(NewVersion)) 
           { 
             return UpdateStatus.ReadyToInstall; 
           } 
           else 
           { 
            return UpdateStatus.Error; 
           } 
       } 

    private static async Task<bool> SaveInstallerToMemoryAsync(string NewVersion) 
      { 
         using (MemoryStream ms = await UpdaterClient.DownloadInstallerAsync(NewVersion)) 
         using (FileStream fs = new FileStream(UpdaterSettings.Path), FileMode.Create)) 
         { 
          if (ms == null) return false; 
          ms.Position = 0; 
          await ms.CopyToAsync(fs); 
          fs.Close(); 
          ms.Close(); 
          return true; 
         } 
      } 

UpdaterClient:

public static async Task<MemoryStream> DownloadInstallerAsync(string version) 
      { 
         string sas = await GetInstallerDownloadLinkAsync(version); 

         CloudBlockBlob blob = new CloudBlockBlob(new Uri(sas)); 

          MemoryStream msRead = new MemoryStream(); 
          blob.DownloadToStream(msRead); 
          return msRead; 
      } 

public static async Task<string> GetInstallerDownloadLinkAsync(string version) 
     { 
        HttpResponseMessage response = null; 
         response = await httpClient.GetAsync(UpdaterSettings.Link + version); 
        if (response.IsSuccessStatusCode) 
        { 
         var res = await response.Content.ReadAsStringAsync(); 
         return res.Trim('"'); 
        } 
     } 
+0

Что вы ожидающий внутри 'DownloadAndSaveInstallerAsync'? –

+0

Выполняется ли метод 'CallUpdateDownload' при создании окна настроек (в конструкторе ... и т. Д.) Или когда отображается окно? – mcy

+0

Внутри существует метод 'await SaveInstallerToMemoryAsync (NewVersion)', который является 'private static async Task SaveInstallerToMemoryAsync (string NewVersion)' - это метод, который работает с 'blob' и' MemoryStream' –

ответ

1

Вы должны выполнить длинные ходовые части внутри задачи/нити и await их избегайте блокировки.

public static async Task<MemoryStream> DownloadInstallerAsync(string version) 
{ 
    string sas = await GetInstallerDownloadLinkAsync(version); 

    CloudBlockBlob blob = new CloudBlockBlob(new Uri(sas)); 

    MemoryStream msRead = new MemoryStream(); 
    await Task.Run(() => blob.DownloadToStream(msRead)); 
    return msRead; 
} 

Update

CloudBlockBlob действительно предлагают DownloadToStreamAsync метод, который вы можете использовать

public static async Task<MemoryStream> DownloadInstallerAsync(string version) 
{ 
    string sas = await GetInstallerDownloadLinkAsync(version); 

    CloudBlockBlob blob = new CloudBlockBlob(new Uri(sas)); 

    MemoryStream msRead = new MemoryStream(); 
    await blob.DownloadToStreamAsync(msRead); 
    return msRead; 
} 
+0

Это сработало. Большое спасибо! –

Смежные вопросы