Task.WaitAll() 未按预期工作

2023-11-22

我正在尝试弄清楚如何使用 Task 类。过去我一直使用常规的 Thread 类,但我正在尝试掌握所有异步编程......

作为示例,我创建了一个包含所有代码的主 Winforms 应用程序。 我的问题的相关代码是:

//Relevant delegates
public delegate void MethodAction(int num);
public delegate void MethodConversion();
public delegate void OnCompletionAction(string completiontext);

//Button user presses
private void button4_Click(object sender, EventArgs e)
{
    richTextBox1.Clear();
    sw.Reset();
    sw.Start();
    Sync.RunAsync3(calcSim);
}

//The method that simulates a calculation by adding a sleep
//the input param threadlength is just to allow threads to take longer than others
//since I'm multithreading, I have to invoke the writing code on the windows RichTextbox control
private void calcSim(int threadlength)
{
    string threadname = Thread.CurrentThread.Name;
    for (int i = 0; i < 10; i++) //Thread calc should take 3s
    {
        Thread.Sleep(300 + threadlength);
        richTextBox1.Invoke((MethodConversion)(() =>
                            { 
                                richTextBox1.AppendText(string.Format("Thread: {0}\tVersion: {1}\n", threadname, (i + 1).ToString())); 
                            }));
    }
}

//Class that contains the different processing methods
public static class Sync
{
    public static event OnCompletionAction OnProcCompletion;

    public static void RunAsync3(MethodAction doM)
    {
        Task[] t = new Task[4];
        for(int i = 0; i < 4; i++)
        {
            t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
        }
        Task.WaitAll(t);
        if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
    }
}

问题出在 Task.WaitAll(t)... 由于某种原因,我无法弄清楚,它完全阻塞了该行并且不再响应。如果我省略该行,表单会实时更新,并且执行大约需要 3 秒。

我的问题是:为什么 Task.WaitAll() 在释放 UI 线程并允许执行其余代码之前不阻塞 UI 线程 3 秒?

我知道它应该阻塞 UI 一段时间(直到计算出所有线程),但它会无限地阻塞整个应用程序。似乎要永远等待?

EDIT

有人建议我使用 WhenAll 而不是 WaitAll。我重写了 RunAsync3 如下:

public static void RunAsync3(MethodAction doM)
{
    Task[] t = new Task[4];
    for(int i = 0; i < 4; i++)
    {
        t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
    }
    //Task.WaitAll(t); -> deadlock
    Task.WaitAll(new Task [] { Task.WhenAll(t) });
    if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}

但这仍然陷入僵局……?我可能错误地使用了 WhenAll ?

EDIT 2

因为每个人都声称我阻塞了 UI 线程是正确的,所以我决定尝试另一种方式:通过在 UI 线程内运行一个新线程作为我的调用线程(以便现在阻塞将发生在我的线程而不是 UI 线程上)。这可行,但显然不是最好的方法!

private void button4_Click(object sender, EventArgs e)
{
    Thread t = new Thread(new ThreadStart(() =>
    {
        richTextBox1.Invoke((MethodConversion)(() => richTextBox1.Clear()));
        sw.Reset();
        sw.Start();
        Sync.RunAsync3(calcSim);
    }));
    t.Start();
}
public static void RunAsync3(MethodAction doM)
{
    Task[] t = new Task[4];
    for(int i = 0; i < 4; i++)
    {
        t[i] = Task.Factory.StartNew((Action)(() => { doM(50 * i); }));
    }
    Task.WaitAll(t);
   //Task.WaitAll(new Task [] { Task.WhenAll(t) });
   if (OnProcCompletion != null) OnProcCompletion("RunSync method finished");
}

你正在造成僵局。

UI 线程正在等待 4 个任务完成。

另一方面,这 4 个任务正在运行calcSim正在尝试调用 UI 线程上的代码 -> 死锁。

你应该使用Task.WhenAll()反而。该方法将返回一个新任务,当所有 for 任务完成时,该任务将被标记为已完成。如果您等待该任务,您的 UI 线程将被释放,所以calcSim将能够调用 UI 线程上的代码,避免死锁。

Update

你用错了。你还在用WaitAll,这是一个阻塞调用。你应该replace它与WhenAll.

await Task.WhenAll(t);

来自文档:

创建一个任务,当所有提供的任务都完成时,该任务将完成 完全的。

通过致电await结果,您的 UI 线程将空闲 - 直到所有 4 个任务完成。当这种情况发生时,你的RunAsync3方法将恢复。

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

Task.WaitAll() 未按预期工作 的相关文章

  • 如何在c++中读取pcap文件来获取数据包信息?

    我想用 C 编写一个程序来读取 pcap 文件并获取数据包的信息 例如 len sourc ip flags 等 现在我找到了如下代码 我认为它会帮助我获取信息 但是我有一些疑问 首先我想知道应该将哪个库添加到我的程序中 然后什么是 pca
  • 计算 Richtextbox 中所有单词的最有效方法是什么?

    我正在编写一个文本编辑器 需要提供实时字数统计 现在我正在使用这个扩展方法 public static int WordCount this string s s s TrimEnd if String IsNullOrEmpty s re
  • 为什么极端下派生类(多重虚拟继承)的大小包括超类成员大小的两倍?

    include
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • 将 Word 文档另存为图像

    我正在使用下面的代码将 Word 文档转换为图像文件 但是图片显得太大 内容不适合 有没有办法渲染图片或将图片保存到合适的尺寸 private void btnConvert Click object sender EventArgs e
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • Apollo graphql 将标头设置为 authmiddleware 不起作用

    我正在使用react native和apollo客户端 如果我尝试通过存储在AsyncStorage中的jwt设置标头 它似乎不起作用 其他不需要标头的解析器工作得很好 我的代码如下所示 import ApolloClient from a
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • CMake 无法确定目标的链接器语言

    首先 我查看了this https stackoverflow com questions 11801186 cmake unable to determine linker language with c发帖并找不到解决我的问题的方法 我
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • 如何在非控制台应用程序中查看 cout 输出?

    输出到调试窗口似乎相当繁琐 我在哪里可以找到cout如果我正在编写非控制台信息 则输出 Like double i a b cout lt lt b lt lt endl I want to check out whether b is z
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData

随机推荐

  • 绝对/相对定位布局溢出

    在相当长的一段时间里 我一直在摆弄一个特定的布局问题 但我显然采用了错误的方式 以下是该方法的基本组成部分 div class stretched div class header SOME HEADER div div class som
  • 身份验证失败:Devise + OmniAuth + Twitter

    我正进入 状态 twitter Authentication failure invalid credentials OAuth Unauthorized 401 Unauthorized成功登录 Twitter 并且页面重定向到登录页面后
  • Hibernate Oracle 表空间注释

    我正在注释我的 DAO 并使用 hibernate3 hbm2ddl 生成 ddls 有没有办法注释表空间 不 没有办法开箱即用 我过去使用以下相当复杂的方法解决了这个问题 创建您自己的注释 TableSpec具有表空间和其他必要的属性 E
  • 复选框的 CSS 边框

    我正在应用 jQuery 复选框的样式 reg checkbox css border thin solid red 边框在 IE 中工作正常 但在 mozilla 中不行 如何使其兼容浏览器 使用大纲 http jsfiddle net
  • Visual Studio 组件缓存已过期

    几乎每次我尝试运行 EF 迁移的 update database 命令时 我都会在 Visual Studio 2015 中收到以下错误 使用 1 个参数调用 GetService 时发生异常 异常 使用 2 个参数调用 Invoke Vi
  • iOS Swift Flood 填充算法

    我为接触点的 桶填充 洪水填充 创建了这个扩展 extension UIImageView func bucketFill startPoint CGPoint newColor UIColor var newRed newGreen ne
  • 如何将模型从一个 Django 应用程序迁移到新的应用程序中?

    我有一个 Django 应用程序 里面有四个模型 我现在意识到这些模型之一应该位于单独的应用程序中 我确实安装了 South 用于迁移 但我不认为这是它可以自动处理的事情 如何将旧应用程序中的模型之一迁移到新应用程序中 另外 请记住 我需要
  • 当没有指定值时,是否应该跳过验证?

    我在 GlassFish 3 上使用 JSF2 我有一个接受可选电话号码的表格 我有这个自定义电话号码验证器 如下 并且我将该字段设置为 required false 因为电话号码在表单中是可选的 问题是 该领域的价值总是得到验证 当没有指
  • ASP.net 对根证书存储的权限

    是否可以授予 asp net 对证书存储的读取权限 如果是 怎么办 如果否 我是否需要为每个证书文件手动设置权限 如果是 这些文件在硬盘上的物理位置在哪里 一般来说 您授予权限A证书 我使用这样的方法来查找定制的证书并授予权限 如果您使用的
  • AngularJs 指令内的数据绑定

    我很难弄清楚如何确保在创建指令时维护双向数据绑定 这是我正在使用的东西和小提琴 http jsfiddle net dkrotts ksb3j 6 HTML
  • ASP.NET Core MVC,从数据库获取文件并渲染为图像

    我将图像数据存储在 SQL 表中 字段类型为varbinary 最大 我还存储图像内容类型 使用 Microsoft ASP NET Core MVC 和 Dapper 我尝试从数据库中获取文件并将其呈现为图像 这是我的文件模型 using
  • 如何使用base64设置图像源

    我想将图像源设置为 base64 源 但它不起作用 JSfiddle net NT9KB img src JavaScript document getElementById img src data image png base64 iV
  • 测试使用 Flask-WTF validate_on_submit 的 POST

    我很难测试 POST 以将类别添加到数据库 在该数据库中我使用 Flask WTF 进行验证和 CSRF 保护 对于CRUD操作请pm我的网站 我使用过 Flask Flask WTF 和 Flask SQLAlchemy 这是我的第一个独
  • 将数据从一个数据库传输到另一个数据库

    如何从一个数据库中取出数据并插入到另一个数据库表中 我不能这样做 请帮助我将数据从一个设备传输到另一个设备 有多种方法可以做到这一点 以下是两个选项 选项1 右键单击 要复制的数据库 选择 任务 gt 生成脚本 选择特定数据库对象 检查 表
  • 具有 Surface 输入的 MediaCodec:生成分块输出

    我正在尝试通过 CameraPreview 数据生成短的连续 mp4 文件MediaCodec createInputSurface 然而 重新创建MediaCodec与其关联的 Surface 需要停止相机以允许再次调用mCamera s
  • XmlSerializer 不使用 sgen 创建的 XmlSerializers.dll

    在我的 Visual Studio 2010 项目中 我使用以下 Post Build 事件命令行来使用 sgen 创建 XmlSerializers dll 构建后事件 ProgramFiles Microsoft SDKs Window
  • Google+ 照片 api [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 有 Google 照片 gdata API 吗 我正在使用谷歌 picasa API但 picasa 对照片有 1 GB 的限制 我想使用我的脚本上
  • 使用 PHP,如何访问从 Stripe API 返回的受保护的 _values 属性?

    我正在整合条纹API与 CMS 我需要归还 values查询中的属性作为数组 以便数据可用作 CMS 中的模板变量 但它始终受到保护 我一直在使用反思类获取数据 但现在我正在使用 Stripe Stripe Plan all 我必须多次调用
  • Pip 选择了错误的路径

    我使用的是 Windows 10 我摆脱了 python 3 8 并安装了 3 7 作为系统上唯一的 python 版本 当尝试使用 pip 安装库时 我现在收到错误 Fatal error in launcher Unable to cr
  • Task.WaitAll() 未按预期工作

    我正在尝试弄清楚如何使用 Task 类 过去我一直使用常规的 Thread 类 但我正在尝试掌握所有异步编程 作为示例 我创建了一个包含所有代码的主 Winforms 应用程序 我的问题的相关代码是 Relevant delegates p