我有一个多年前的 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
。
我已经尝试附加.ConfigureAwait(true)
到异步调用,这没有区别。也不会与 . 同步运行调用.GetAwaiter().GetResult()
。
谁能解释为什么窗口的尺寸会随着这个特定的异步调用而改变,和/或如何防止这种情况发生?
更新
根据请求,这是一个引发解释行为的代码示例。我可以看到这里没有发生任何异常,但我向您保证,正是这段代码导致了解释的行为。
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
}
其他一些可能相关的信息:
FormBorderStyle
窗口是“FixedToolWindow ”- 窗口在启动方法中被赋予了明确的宽度
AutoSize
= 假AutoSizeMode
= 只成长- 正在开发它的计算机没有具有新缩放逻辑的 Windows 10 1703 (Creator's) 更新
- 如果
GetprojectTemplateFile
方法不是异步的,即有签名,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 编译器认为这是一种可能性,所以......它重新呈现表单?
此外,重要的是,此代码不在表单的代码隐藏中,它在一个类中,该类在其构造函数中为表单提供了一个实例。