我有一个已有几年历史的 WinForms 项目,并且已经使用异步事件处理程序进行了改造:
private async void dgvNewOrders_CellClick(object sender, DataGridViewCellEventArgs e)
该方法内部是一个异步调用:
var projectTemplate = await GetProjectTemplateFile(companyId, sourceLang, targetLang);
当程序在正常分辨率屏幕上运行时,它会按预期运行。但是,当在高 DPI 屏幕上运行时,窗口的尺寸以及所有子控件的尺寸一旦遇到内部异步调用就会跳到一半大小。就好像程序突然以兼容模式运行或缩放已被禁用。
目前,为了解决该问题,GetProjectTemplateFile
方法简单地包括
private async Task<ProjectTemplateFile> GetProjectTemplateFile(long companyId, string sourceLanguage, string targetLanguage)
{
return null;
}
是否没有区别GetProjectTemplateFile
是否执行异步操作。
如果我注释掉异步调用GetProjectTemplateFile
然后程序按预期运行,维度上没有任何跳跃,即使在CellClick
event.
我尝试过附加.ConfigureAwait(true)
到异步调用,这没有什么区别。也不与同步运行调用.GetAwaiter().GetResult()
.
谁能解释为什么窗口的尺寸会随着这个特定的异步调用而改变,和/或如何防止这种情况发生?
Update
根据请求,这里是一个代码示例,它引发了所解释的行为。我可以看到这里没有发生任何异常情况,但我向您保证,正是这段代码导致了所解释的行为。
private async void dgvNewOrders_CellClick(object sender, DataGridViewCellEventArgs e)
{
var result = await _templateInteraction.GetProjectTemplateFile(1,
"en-US",
"de-CH");
return;
}
public class TemplateInteraction : ITemplateInteraction
{
public async Task<ProjectTemplateFile> GetProjectTemplateFile(long companyId, string sourceLanguage, string targetLanguage)
{
return null;
// elided code
}
// other methods
}
其他一些可能相关的信息:
- The
FormBorderStyle
窗口的名称是“FixedToolWindow”
- 在启动方法中为窗口指定了明确的宽度
-
AutoSize
= False
-
AutoSizeMode
= 只成长
- 正在开发的计算机没有 Windows 10 1703
(创作者)更新,具有新的缩放逻辑
- If the
GetprojectTemplateFile
方法是not async, i.e.有签名public ProjectTemplateFile GetProjecttemplateFile(...)
那么就没有问题了。这个问题似乎仅在方法调用是异步时才存在 - 即使我将其设置为阻塞调用。
更新2:
我找到了导致此问题的特定代码行:
MessageBox.Show(...);
内部异步调用,GetProjectTemplateFile
,调用 API,然后检查响应:
var responseMessage = await client.GetAsync(uri);
if (!responseMessage.IsSuccessStatusCode)
{
MessageBox.Show(...);
return null;
}
如果我注释掉MessageBox.Show(...)
调用后一切正常,没有缩放问题,没有尺寸跳跃。
但是当MessageBox.Show(...)
呼叫就位。
此外,API 响应 200(OK),因此 MessageBox 代码甚至没有被使用。我的猜测是 JIT 编译器认为这是一种可能性,所以......它重新呈现表单?
另外,重要的是,此代码不在表单的代码隐藏中,而是在一个类中,在其构造函数中为表单提供了一个实例。