简体   繁体   English

异步方法挂起UI

[英]Async method hangs UI

I have a window, which uses some async methods. 我有一个窗口,它使用一些异步方法。 However, it only hangs UI (during these operations) only if i create it on runtime, like this: 但是,只有在运行时创建UI时,它才会挂起UI(在这些操作期间),如下所示:

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

However, if I create it like this: 但是,如果我这样创建它:

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

Everything seems to be OK and UI is not hanging. 一切似乎都还可以,并且UI没有挂起。

The methods inside the window, that cause the problems are presented below: 窗口内导致问题的方法如下所示:

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

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

The main hang occurs on this string inside DownloadAndSaveInstallerAsync : 主要挂起发生在DownloadAndSaveInstallerAsync以下字符串上:

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

The question is , why this happens? 问题是 ,为什么会这样? Why creating the window on start prevents it from hanging from async methods. 为什么在启动时创建窗口会阻止其从异步方法挂起。

The other question is , that I have another object, which also uses DownloadAndSaveInstallerAsync method. 另一个问题是 ,我还有另一个对象,该对象也使用DownloadAndSaveInstallerAsync方法。 These objects are created on runtime, and I can't do anything to prevent this hanging, occuring on download. 这些对象是在运行时创建的,我无法采取任何措施防止这种情况在下载时发生挂起。

How can I prevent UI from hanging in this situation (creating objects on runtime)? 如何防止UI在这种情况下挂起(在运行时创建对象)?

More code below: 下面的更多代码:

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

UpdaterLogic: 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: 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('"');
                    }
        }

You have to execute the long running parts inside a task/thread and await them to avoid blocking. 您必须在任务/线程中执行长时间运行的部分,并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 does offer an DownloadToStreamAsync method which you can use 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM