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 窗口在遇到异步调用时会更改尺寸 的相关文章

  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • Visual Studio 在构建后显示假错误

    我使用的是 Visual Studio 2017 构建后 sln在调试模式下 我收到错误 但是 当我通过双击错误列表选项卡中的错误来访问错误时 错误会从页面中消失 并且错误数量也会减少 我不太确定这种行为以及为什么会发生这种情况 有超过 2
  • C# 数据表更新多行

    我如何使用数据表进行多次更新 我找到了这个更新 1 行 http support microsoft com kb 307587 my code public void ExportCSV string SQLSyntax string L
  • unordered_map 中字符串的 C++ 哈希函数

    看起来 C 标准库中没有字符串的哈希函数 这是真的 在任何 c 编译器上使用字符串作为 unordered map 中的键的工作示例是什么 C STL提供模板专业化 http en cppreference com w cpp string
  • 告诉 Nancy 将枚举序列化为字符串

    Nancy 默认情况下在生成 JSON 响应时将枚举序列化为整数 我需要将枚举序列化为字符串 有一种方法可以通过创建来自定义 Nancy 的 JSON 序列化JavaScript 原始转换器 https github com NancyFx
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 为什么从字典中获取时会得到 Action<> 的克隆?

    我有以下字典 private Dictionary
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • 将数组作为参数传递

    如果我们修改作为方法内参数传递的数组的内容 则修改是在参数的副本而不是原始参数上完成的 因此结果不可见 当我们调用具有引用类型参数的方法时 会发生什么过程 这是我想问的代码示例 using System namespace Value Re
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐