WinForms 窗口在遇到异步调用时会更改尺寸

2023-12-26

我有一个已有几年历史的 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 编译器认为这是一种可能性,所以......它重新呈现表单?

另外,重要的是,此代码不在表单的代码隐藏中,而是在一个类中,在其构造函数中为表单提供了一个实例。


我猜您正在使用 System.Windows 命名空间中的 MessageBox,从PresentationFramework.dll 引用,而不是 System.Windows.Forms 命名空间?

// Causes DPI scaling problems:
System.Windows.MessageBox.Show() // loads WPF version from PresentationFramework.dll

// no DPI scaling issues:
System.Windows.Forms.MessageBox.Show() // uses standard winforms messagebox

因此,请尝试使用标准 MessageBox。

我发现每当任何以 WPF 为目标的 dll 加载到内存中时,DPI 自动缩放都会重置。甚至不需要实际调用特定函数 - 一旦调用父函数,就会加载 dll。

我遇到了同样的问题,只是使用 System.Windows.Input.Keyboard.IsKeyToggled() 加载了PresentationCore.dll。还以为我要疯了……

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WinForms 窗口在遇到异步调用时会更改尺寸 的相关文章

  • 如何使用 ILoggerFactory 记录 Polly 的重试

    或者 如何从静态方法记录 From https github com App vNext Polly https github com App vNext Polly你有这样的例子 其中记录器神奇地可用 Policy Timeout 30
  • 使用 C++ 拆分“[常规设置]”格式的节字符串

    我是 C 新手 我想读取包含部分和键值对的 ini 文件 根据部分 我想读取相应键的值 首先 我想阅读方括号内的部分 请帮忙 谢谢 对于真正的 INI 文件解析 我强烈建议iniparser库 http ndevilla free fr i
  • 每次调用新方法时触发事件

    我正在做一个logger for a c 应用程序需要记录每个方法被调用的时间以及每个方法执行时间 我可以通过调用自己的方法来做到这一点EventLogger LogMethodCall方法在每个方法的开头 但我想知道是否有办法使CLR每次
  • Confuser .NET 混淆器。安全吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我目前正在开发一个应用程序 其中阻止用户反编译代码非常重要 现在 我意识到 如果由经验丰富的程序员执行 大多数 exe 都是可反编译的
  • C++:将模板参数的模板类型成员添加为好友的正确语法?

    我有一个带有模板类型参数 tTRAIT 的类 我想加一个模板为好友type member aliastTRAIT 但我无法弄清楚语法 这可能吗 template
  • 无缝滚动瓷砖地图

    我正在开发一个自上而下的角色扮演游戏 并且想要实现无缝滚动地图 也就是说 当玩家探索世界时 地图之间没有加载屏幕 也没有通往下一个区域的 门 我有两种方法可以打破世界 在顶层 我有 区域 它只是 9 个 地图 的集合 这些区域仅由目录表示
  • 读取STM32 MCU SPI数据寄存器的值

    有很多类似的问题 但似乎没有一个问题完全相同 我正在将 STML4 MCU 连接到 6 轴传感器 LSM6DS3 我已经成功地在 I2C 中实现了所有内容 但想要 SPI 的额外速度 和 DMA 如果我能让这些第一步工作起来的话 因此 第一
  • WinForms - 表单大小错误

    我们有以下代码 private void MainForm Shown object sender EventArgs e RepositionForm private void RepositionForm Rectangle rect
  • C++:初始化静态字符串成员

    我在 C 中初始化静态字符串成员时遇到一些问题 我有几个类 每个类都包含几个表示 id 的静态字符串成员 当我通过调用静态函数初始化变量时 一切都很好 但是 当我想为一个变量分配另一个变量的值时 它仍然保留空字符串 这段代码有什么问题 st
  • 命名空间“Microsoft”中不存在类型或命名空间名称“Practices”

    我正在使用 Microsoft Visual Studio 2005 for c 我的代码中有以下命名空间 using Microsoft Practices EnterpriseLibrary using Microsoft Practi
  • 如何填充两个样条线或直线系列之间的区域

    我有这个Chart 如何填充两个之间的区域Series S0 and S1 说蓝色和黄色Series 为此 我们编写了其中之一Paint事件 这里的ValueToPixelPosition https msdn microsoft com
  • ASP.NET MVC 路由 - 向路由添加 .html 扩展名

    我对 MVC 和路由非常陌生 我被要求修改一个应用程序以使用不同的 url 由于我没有经验 这项任务对我来说有点困难 好吧 让我们谈谈一些代码 routes MapRoute CategoryBySeName Route name prod
  • 将一个整数从 C 客户端发送到 Java 服务器

    我使用此代码将一个整数从我的 Java 客户端发送到我的 Java 服务器 int n rand nextInt 50 1 DataOutputStream dos new DataOutputStream socket getOutput
  • 带有自定义鉴别器的 EntityFramework Code First 继承

    我正在尝试在 EntityFramework Code First 中映射以下继承 public class Member public string ProjectName get set public string AssemblyNa
  • SQL参数化查询不显示结果

    我的 DataAcess 类中有以下函数 但它没有显示任何结果 我的代码如下 public List
  • 该组件没有由 uri 标识的资源

    我想创建一个通用数据网格以在我的所有视图 用户控件上使用 这是我的结构 Class Library called Core Class called ViewBase public class ViewBase UserControl pu
  • EWS - 给予预约,获取预约的所有者副本

    在 EWS 中进行预约后 是否可以获得所有者的副本 例如 如果我登录为user1 我有user1创建的约会的副本user2 我有冒充权 我要编辑user2预约的副本 我怎样才能获得user2 s copy 您可以使用 PidLidClean
  • 未找到 _sqlite3_open 等符号错误

    您好 我收到此错误 Undefined symbols sqlite3 open referenced from main in ccRlWVer o sqliite3 close referenced from main in ccRlW
  • 如何在给定点停止线程?

    我试图停止一些线程 阅读一些有关优雅地执行此操作的正确方法的内容 但我一定做错了什么 因为它根本不起作用 起初我尝试不使用lock with IsRunning不稳定 然后尝试使用锁 这是我所拥有的 private volatile boo
  • 获取会议组织者邮件地址 EWS API

    我想使用 EWS API 获取会议组织者的邮件地址 目前 我刚刚获得约会项目的一些属性 我听说你可以设置你想要获取哪些属性 我的代码看起来像这样 CalendarView cview new CalendarView start end c

随机推荐