【发布时间】:2016-09-07 08:51:00
【问题描述】:
我有一个窗口,它使用了一些异步方法。但是,只有当我在运行时创建它时,它才会挂起 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();
}
一切似乎都正常,UI 没有挂起。
窗口内导致问题的方法如下:
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 方法。这些对象是在运行时创建的,我无法做任何事情来防止这种挂起,在下载时发生。
如何防止 UI 在这种情况下挂起(在运行时创建对象)?
更多代码如下:
private async void CallUpdateDownload()
{
UpdaterStatus.CurrentUpdateStatus = await UpdaterLogic.DownloadAndSaveInstallerAsync(UpdaterStatus.freshVersion);
}
更新逻辑:
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;
}
}
更新客户端:
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('"');
}
}
【问题讨论】:
-
你在
DownloadAndSaveInstallerAsync里面等什么? -
方法
CallUpdateDownload是在设置窗口创建时(在构造函数中...等)还是在窗口显示时运行? -
在里面,有一个方法
await SaveInstallerToMemoryAsync(NewVersion),它的头是private static async Task<bool> SaveInstallerToMemoryAsync(string NewVersion)——就是这个方法,它可以和blob和MemoryStream一起使用 -
CallUpdateDownload被窗口内的按钮点击调用 -
请在此处显示所有涉及的代码。
标签: c# winforms asynchronous