为什么在等待方法之后的代码中没有使用初始线程?

2023-12-11

我不明白使用 async-await 时如何将控制返回给调用者,因为当我执行此代码时,第一个线程在等待方法内调用任务时实际上被销毁,并且给出结果的线程执行所有剩余代码下面我也画了一个我认为执行的图,但似乎是错误的。

根据“将控制权返回给调用者”假设的工作流程:

Results

Results

enter image description here

Main

           public static string GetThreadId => Thread.CurrentThread.ManagedThreadId.ToString();

           static async Task Main(string[] args) {
                Console.WriteLine("From main before async call , Thread:" + GetThreadId);

                string myresult = await TestAsyncSimple();

                Console.WriteLine("From main after async call ,Thread:" + GetThreadId);
                Console.WriteLine("ResultComputed:" + myresult+",Thread:"+GetThreadId);
                Console.ReadKey();

            }

异步任务

         public static async Task<string> TestAsyncSimple() {

            Console.WriteLine("From TestAsyncSimple before delay,Thread:" + GetThreadId);
            string result=await Task.Factory.StartNew(() => {
                Task.Delay(5000);
                Console.WriteLine("From TestAsyncSimple inside Task,Thread:" + GetThreadId);
                return "tadaa";
                });
            Console.WriteLine("From TestAsyncSimple after delay,Thread:" + GetThreadId);
            return result;
           }

谁能指出我正确的方向?还有什么原因导致新线程产生?总是在启动任务时?除了创建将执行剩余代码的新线程的任务之外,还有其他“触发器”吗?


async Main 方法转换为如下所示:

static void Main() {
    RealMain().GetAwaiter().GetResult();
}

static async Task RealMain() {
    // code from async Main
}

考虑到这一点,在“异步调用之前的主线程”点,您位于主应用程序线程(id 1)上。这是常规(非线程池)线程。您将在此线程上,直到

await Task.Factory.StartNew(...)

在此刻,StartNew启动一个新任务,该任务将在线程池线程上运行,该线程是从池中创建或获取的(如果可用)。这是您示例中的线程 3。

当你到达await- 控制权返回给调用者,本例中的调用者是线程 1。在重新等待之后,该线程会做什么?这里被屏蔽了:

 RealMain().GetAwaiter().GetResult();

等待结果RealMain.

现在线程3已经执行完毕但是TestAsyncSimple()有更多代码要运行。如果在等待之前没有同步上下文(这里的情况 - 在控制台应用程序中)-等待之后的部分将在可用的线程池线程上执行。由于线程 3 已完成其任务的执行 - 它可用并且能够继续执行其余任务TestAsyncSimple() and Main()功能,它确实做到了。如上所述,线程 1 一直被阻塞 - 因此它无法处理任何延续(它很忙)。此外,它也不是线程池线程(但这与这里无关)。

当你到达之后Console.ReadKey然后按下一个键——Main任务最终完成,线程1(等待该任务完成)被解除阻塞,然后它从真正的Main函数返回并且进程被终止(仅在此时线程1被“销毁”)。

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

为什么在等待方法之后的代码中没有使用初始线程? 的相关文章

随机推荐

  • 有什么方法可以在运行时调试电子表格应用程序脚本吗? [复制]

    这个问题在这里已经有答案了 有没有办法在运行时调试电子表格谷歌应用程序脚本 仅通过脚本编辑器运行它是没有用的 因为我需要调试的函数将触发事件作为参数 这是一个可以测试表单提交触发功能的函数 摘自如何测试 GAS 中的触发功能 functio
  • 尽管有标志,Chrome 并不将不安全的来源视为安全

    我想测试getUserMediaWindows 上 Chrome 上的不安全来源 我按照 goo gl rStTGz 上的说明以这种方式启动 Chrome 如果您使用不安全的来源 该链接会显示在控制台中getUserMedia start
  • 了解更多有关 JS 身高的快速资源

    JavaScript 中有很多与 高度 相关的属性 clientHeight Window height scrollHeight offsetHeight 等 我可以猜测他们是做什么的 但我想要一份正式的 详细的指南 通用谷歌搜索没有帮助
  • .net core类库调用.net Framework类库

    无法找到我的疑问的答案 希望有人能澄清 我创建了一个虚拟解决方案 1个类库 net框架 1 net核心库 试图参考任何一种方式 但我不能 它们不兼容 罚款是有道理的 现在我的问题 我有一个实用类库 net 框架 带有扩展 助手等 winfo
  • C# - 在背景图像上绘制顶部图像(alpha 通道) - WinForm

    我已经得到了这个带有 alpha 通道的顶部图像 我需要将此图像放在另一个背景图像上 而顶部图像的 alpha 通道显然保持完整 现在我已经看到了一些关于 Canvas 的教程 但我的项目似乎无法识别 Canvas 有人知道为什么我不能使用
  • 初始化条带变量后如何更改条带区域设置

    我正在使用条纹TypeScript应用程序 我读到可以使用如下语言环境设置 stripe 变量 var stripe Stripe pk test locale en 但如果我想在初始化后更改语言 我无法做到这一点 我想创建一个新的 str
  • 是否可以使用 SSH.NET 从单个登录会话执行多个 SSH 命令?

    我将 C 与 SSH NET 结合使用 并且能够使客户端 SSH 连接正常工作 以便通过 SSH 执行命令 我可以毫无问题地连接到虚拟机管理程序虚拟机上安装的 Linux 请读回StdOut and StdErr etc 然而 每个命令就像
  • 使用 Windows 服务进行屏幕截图

    即使有很多关于这个问题的问题 我也找不到合适的解决方案 我正在创建 Windows 服务来捕获屏幕 Windows 7 我尝试使用 Windows 应用程序 它工作正常 当我要启动该服务时 它说我无法启动该服务 当我检查 Windows 日
  • 单击图表时获取 X 轴值 - Excel VBA

    我遇到了一个奇怪的需求 当用户单击图表区域时 我需要从图表中获取 X 轴值 我知道我们可以为图表分配一个宏 这样 就可以创建图表的事件 但不知道如何进一步进行 请问有什么想法吗 Thanks 如果您的图表位于图表工作表中 则可以右键单击图表
  • “[变量] 在定义之前已被使用”错误

    我有几个这样的错误 我不知道如何 正确 解决它 问题是我有很多 javascript 文件 分开以便于维护 并且我包含插件等 所以在这个例子中我使用来自的快捷方式http www openjs com scripts events keyb
  • 删除缺失值超过阈值的行缺失值[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 目前不接受答案 我有一个带有一些缺失值的矩阵 A lt array c 1 NA 3 NA 4 5 7 NA 2 dim c 3 3 我可以使用删除所有具有缺失值的行 B lt na omi
  • Applescript 使用特定库启动 iTunes

    我想编写一个 AppleScript 它允许我使用给定的库启动 iTunes 而不必按住 Option 键并浏览某个库 我已经知道道格的图书馆经理 但这并不是我想要的 AppleScript 将用于特定的库 iTunes 不允许您使用 Ap
  • 避免身份列中的空白

    我有一张桌子在MS SQL SERVER 2008我已经设置了它primary key自动递增 但如果我从此表中删除任何行并在表中插入一些新行 它将从下一个标识值开始 这会在标识值中创建间隙 我的程序要求所有身份或密钥按顺序排列 喜欢 分配
  • JavaScript 使用过滤器和循环从数组中删除多个值

    我是新来的 需要一些编写函数的帮助destroyer 从数组中删除多个值 destroyer 函数传入一个数组和附加数字作为参数 这个想法是从数组中删除数字 E g destroyer 1 2 3 1 2 3 2 3 Output 1 1
  • 如何转换Big Endian以及如何翻转最高位?

    我正在使用 TStream 读取二进制数据 感谢这篇文章 如何使用 TFileStream 将二维矩阵读入动态数组 我的下一个问题是数据是大端字节序 根据我的阅读 Swap 方法似乎已被弃用 我如何交换以下类型 16 bit two s c
  • 为ARM处理器编译基本C文件

    我正在使用 GCC 工具链的 Yagarto 重新编译 我正在尝试编译这个简单的程序以获得 elf可执行文件 int main void return 0 当输入命令时arm none eabi gcc main c我收到错误消息 c ya
  • 类型错误:无法在“URL”上执行“createObjectURL”:未找到与提供的签名匹配的函数

    我有一个 Angular 8 应用程序 我用 jasmine karma 做了一些单元测试 这是 component ts export class DossierPersonalDataComponent implements OnIni
  • 如何在 IndexedDB 中保存对象?

    我想将我的API数据存储在浏览器的indexedDB中 我本想尝试本地存储 但它的限制为 5MB 但我的 JSON 数据超过 7MB 我想保存在indexedDB中以便更快地访问 我想以 JSON 格式保存整个数据 但不知道如何设置索引数据
  • Java Tab顺序:如何在java swing表中设置Tab顺序

    我是 java 语言新手 我想在其中设置制表符顺序JTable在java摇摆中 我们如何在java swing中设置Tab顺序 我假设您指的是 FocusTraversalPolicy 不确定这是否很容易在 JTable 内部处理 但是这里
  • 为什么在等待方法之后的代码中没有使用初始线程?

    我不明白使用 async await 时如何将控制返回给调用者 因为当我执行此代码时 第一个线程在等待方法内调用任务时实际上被销毁 并且给出结果的线程执行所有剩余代码下面我也画了一个我认为执行的图 但似乎是错误的 根据 将控制权返回给调用者