取消任务关闭窗口。如何检测任务是否同步返回?

2024-04-15

我遵循一种相当常见的模式,使用异步对话框方法确认/取消主窗口关闭。但是,在我调用来呈现对话框的异步任务中,在某些情况下我会立即返回布尔值,而不是等待对话框任务方法的返回。在这些情况下会抛出异常:

System.InvalidOperationException:“在窗口关闭时无法将可见性设置为可见或调用 Show、ShowDialog、Close 或 WindowInteropHelper.EnsureHandle。”

It seems这是因为异步任务同步返回并在窗口上调用 Close(),而不是调用其余代码作为延续。除了在 try/catch 中包装 Close() 或在返回 bool 之前在函数中添加 Task.Delay() 之外,还有其他方法可以检测我是否应该在窗口上调用 Close() 吗? (即,如果任务同步返回)

或者...我在概念上遗漏了异步/等待模式中的某些内容吗?

这是我的代码:

private bool _closeConfirmed;

private async void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
    //check if flag set
    if(!_closeConfirmed)
    {
        //use flag and always cancel first closing event (in order to allow making OnClosing work as as an async function)
        e.Cancel = true;

        var cancelClose = await mainViewModel.ShouldCancelClose();

        if(!cancelClose)
        {
            _closeConfirmed = true;
            this.Close();
        }
    }
}

异步函数如下所示:

public async Task<bool> ShouldCancelClose()
{
    if(something)
    {
        var canExit = await (CurrentMainViewModel as AnalysisViewModel).TryExit();

        if (!canExit) //if user cancels exit
            return true;

        //no exception
        return false;
    }

    //this causes exception
    return false;
}

例外情况是你不能打电话Close()OnClosing事件正在运行。我想你明白这一点。

有两种方法可以处理这个问题。

First,使用了 Herohtar 在评论中提到的答案await Task.Yield() https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.yield?view=netframework-4.8.

更具体地说,关键是等待任何不完整的Task.

原因是因为async方法开始同步运行,就像任何其他方法一样。这await关键字只有在给出不完整的值时才会做任何有意义的事情Task。如果给定一个Task已经完成的,该方法同步继续.

那么让我们看一下您的代码。首先我们假设something is true:

  1. MainWindow_OnClosing开始同步运行。
  2. ShouldCancelClose开始同步运行。
  3. TryExit()被调用并返回一个不完整的Task.
  4. The await关键字看到不完整Task并返回一个不完整的Task。控制权返回到MainWindow_OnClosing.
  5. The await in MainWindow_OnClosing看到不完整的Task,所以它返回。由于返回类型是void,它什么也不返回。
  6. 控制权返回到表单,并且由于它无法等待其余部分MainWindow_OnClosing,它假设事件处理程序已完成。
  7. 每当TryExit()完成,剩下的ShouldCancelClose and MainWindow_OnClosing runs.
  8. If Close()现在被调用,它有效,因为据表单所知,事件处理程序在第 6 步完成.

现在我们假设something is false:

  1. MainWindow_OnClosing开始同步运行。
  2. ShouldCancelClose开始同步运行。
  3. ShouldCancelClose返回一个已完成的Task值为false.
  4. The await关键字在MainWindow_OnClosing看到完成的Task并继续运行该方法同步地.
  5. When Close()被调用,它抛出异常因为事件处理程序尚未完成运行.

所以使用await Task.Yield()只是一种等待的方式不完整的东西以便控制权返回到表单,因此它认为事件处理程序已完成。

Second,如果您知道没有异步代码运行,那么您可以依赖e.Cancel是否取消平仓。您可以通过不等待来检查Task直到你知道它是否完整。这可能看起来像这样:

private bool _closeConfirmed;

private async void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
    //check if flag set
    if(!_closeConfirmed)
    {

        var cancelCloseTask = mainViewModel.ShouldCancelClose();

        //Check if we were given a completed Task, in which case nothing
        //asynchronous happened.
        if (cancelCloseTask.IsCompleted)
        {
            if (await cancelCloseTask)
            {
                e.Cancel = true;
            }
            else
            {
                _closeConfirmed = true;
            }
            return;
        }

        //use flag and always cancel first closing event (in order to allow making OnClosing work as as an async function)
        e.Cancel = true;

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

取消任务关闭窗口。如何检测任务是否同步返回? 的相关文章

  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 嵌套异步/等待 Nodejs

    似乎无法弄清楚为什么这对我不起作用 我有一个父函数 它对子加载进程执行 AWAIT LOAD 进程又调用另一个名为 LOADDATA 的 AWAIT 所以基本上是这样的 module exports async function try a
  • 为什么基类必须有一个带有 0 个参数的构造函数?

    这不会编译 namespace Constructor0Args class Base public Base int x class Derived Base class Program static void Main string a
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 当我单击 C# 中的“取消”按钮时重定向到新页面(Web 部分)

    Cancel button tc new TableCell btnCancel new Button btnCancel Text Cancel btnCancel Click new EventHandler btnCanel Clic
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • try-catch 中未处理的异常

    try list from XElement e in d Descendants wix File where e Attribute Name Value Contains temp Name e Parent Parent Attri
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 为什么 FTPWebRequest 或 WebRequest 通常不接受 /../ 路径?

    我正在尝试从 ftp Web 服务器自动执行一些上传 下载任务 当我通过客户端甚至通过 Firefox 连接到服务器时 为了访问我的目录 我必须指定如下路径 ftp ftpserver com AB00000 incoming files
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 无法使用 Ninject 将依赖项注入到从 Angular 服务调用的 ASP.NET Web API 控制器中

    我将 Ninject 与 ASP NET MVC 4 一起使用 我正在使用存储库 并希望进行构造函数注入以将存储库传递给其中一个控制器 这是实现 StatTracker 接口的上下文对象 EntityFramework public cla
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 我应该在应用程序退出之前运行 Dispose 吗?

    我应该在应用程序退出之前运行 Dispose 吗 例如 我创建了许多对象 其中一些对象具有事件订阅 var myObject new MyClass myObject OnEvent OnEventHandle 例如 在我的工作中 我应该使
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 以编程方式使用自定义元素创建网格

    我正在尝试以编程方式创建一个网格 并将自定义控件作为子项附加到网格中 作为 2x2 矩阵中的第 0 行第 0 列 为了让事情变得更棘手 我使用了 MVVM 设计模式 下面是一些代码可以帮助大家理解这个想法 应用程序 xaml cs base
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens

随机推荐

  • VB.NET中有条件三元运算符吗?

    在 Perl 和其他语言 中 条件三元运算符可以表示如下 my foo bar buz cat dog VB NET中有类似的运算符吗 取决于版本 这IfVB NET 2008 中的运算符是三元运算符 以及空合并运算符 这是刚刚推出的 20
  • 如何将Processing核心库与Maven一起使用?

    我想在我的 Maven 项目中使用处理库 但我找不到任何依赖项 我在哪里可以得到它 Edit 从处理 3 开始 官方文物 https mvnrepository com artifact org processing core发布到 Mav
  • Laravel 5.6 Passport OAuth 最大登录尝试次数

    我刚刚使用 Laravel Passport 创建了一个简单的 OAuth 系统 该系统将负责外部应用程序的用户注册和身份验证 一切都按我的预期进行 现在我想实现一种机制 在预定义的失败登录尝试次数后锁定用户 我是 Laravel 和 Pa
  • 如何跟踪同一函数的多次运行?

    我有一个这样的函数 function run arg if window alreadyRun init window alreadyRun true more code 你明白了 我想弄清楚这是否是第一次调用函数 有一个更好的方法吗 不使
  • QT画一个圆[重复]

    这个问题在这里已经有答案了 我正在学习 QT 有一个简单的问题 画一个半径为 r 中心点为 x y 的圆的最佳方法是什么 Thanks In a paintEvent用这个 http doc qt io qt 4 8 qpainter ht
  • 如何防止mysql重置自动增量值?

    我有一个表来制作临时 id s 当我删除表中的所有行时 该表的自动增量值将重置为 0 但我不想重置自动增量 我能做些什么 Compare 截断表 http dev mysql com doc refman 5 5 en truncate t
  • spring-integration并行分割路由聚合流由于单向MessageHandler而失败

    我想通过拆分项目 将每个项目路由到适当的网关并聚合结果来并行处理项目列表 但是 我的应用程序无法启动 出现以下错误 BeanCreationException The currentComponent is a one way Messag
  • 将正文添加到与 azure 服务 mgmt api 一起使用的 HttpWebRequest

    我将如何添加到 HttpWebRequest 的正文 身体需要由以下部分组成
  • Javascript 单击打开和关闭菜单,不使用 jquery

    我想要一个菜单 可以单击打开 然后单击关闭 与悬停菜单类似 但需要单击 打开和单击关闭 我有三个可见的列表项 下面有子菜单 这些是用 css display none 隐藏的 我可以让它们显示 使用关键字 this 以及一个用于检查是否有
  • 如何检查 Perl 中打开(文件)是否成功?

    下面的代码 不太像 Perl 风格 usr bin perl if e mydir print directory doesn t exist n open my fh gt mydir file txt if fh print file
  • 设置 npm 注册表 URL 的用户名和密码

    我正在尝试使用 npm 从 url 安装软件包 http 主机 80 http host 80 我做了以下事情 npm 配置设置 strict ssl false npm 配置设置注册表 npm 代理http 主机 端口 http host
  • JavaScript - 控制 document.write 的插入点

    我想创建一个运行第三方脚本的页面 其中包括document write当 DOM 已经完全加载之后 我的页面不是 XHTML 我的问题是 document write 正在覆盖我自己的页面 这就是 DOM 加载后它所做的事情 我尝试重写 d
  • 使用谷歌地图 API iOS 进行反向地理编码

    我正在使用以下代码进行反向地理编码 void locationManager CLLocationManager manager didUpdateToLocation CLLocation newLocation fromLocation
  • Facebook API 人物搜索按国家/地区过滤

    我正在尝试使用 Facebook API Graph API 或 FQL 以有效者为准 搜索人员 到目前为止 它工作得很好 但我无法按国家或语言对其进行过滤 我目前正在检索此网址 https graph facebook com searc
  • 无法分配给变量,因为它是借用的

    我试图在循环中重新分配变量 但我不断遇到cannot assign to cur node because it is borrowed 下面为了简单起见我注释掉了循环 这是同样的问题 我该如何处理这个问题 fn naive largest
  • Java 未知格式转换异常

    下面的代码引发了这个错误 我不知道为什么 将 String format 输出到str变量 但我不知道它出了什么问题 Exception in thread main java util UnknownFormatConversionExc
  • Android 中的屏幕截图

    我想开发一个应用程序来截取 android 屏幕的屏幕截图 有人知道怎么做吗 这类似于 koushik duttas 屏幕截图 但是没有使用 root 并且有人有 koushik dutta 屏幕截图应用程序正在运行 不适合我 请让我知道
  • Kubernetes Dashboard 在整个网站上都是“被禁止的”

    我在 Kubernetes 的仪表板网站上到处都看到 被禁止 见图 重现 通过站点而不是从 shell 创建 Google Kubernetes 集群 选择 Kubernetes 版本 1 8 6 通过连接按钮打开外壳 gcloud con
  • Autobahn websockets Android 演示崩溃

    我是 websockets 的新手 我一直在使用 Autobahn websocket 来制作一个更大的项目 它在 python 和 js 版本中工作得很好 但我在 Android API 上遇到了麻烦 我正在遵循中的教程http www
  • 取消任务关闭窗口。如何检测任务是否同步返回?

    我遵循一种相当常见的模式 使用异步对话框方法确认 取消主窗口关闭 但是 在我调用来呈现对话框的异步任务中 在某些情况下我会立即返回布尔值 而不是等待对话框任务方法的返回 在这些情况下会抛出异常 System InvalidOperation