C# async/await 控制台应用程序中的奇怪行为

2023-11-21

我构建了一些异步/等待演示控制台应用程序并得到了奇怪的结果。代码:

class Program
{
    public static void BeginLongIO(Action act)
    {
        Console.WriteLine("In BeginLongIO start... {0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(1000);
        act();
        Console.WriteLine("In BeginLongIO end... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
    }

    public static Int32 EndLongIO()
    {
        Console.WriteLine("In EndLongIO start... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(500);
        Console.WriteLine("In EndLongIO end... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        return 42;
    }

    public static Task<Int32> LongIOAsync()
    {
        Console.WriteLine("In LongIOAsync start... {0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        var tcs = new TaskCompletionSource<Int32>();
        BeginLongIO(() =>
        {
            try { tcs.TrySetResult(EndLongIO()); }
            catch (Exception exc) { tcs.TrySetException(exc); }
        });
        Console.WriteLine("In LongIOAsync end... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        return tcs.Task;
    }

    public async static Task<Int32> DoAsync()
    {
        Console.WriteLine("In DoAsync start... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        var res = await LongIOAsync();
        Thread.Sleep(1000);
        Console.WriteLine("In DoAsync end... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        return res;
    }

    static void Main(String[] args)
    {
        ticks = DateTime.Now.Ticks;
        Console.WriteLine("In Main start... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        DoAsync();
        Console.WriteLine("In Main exec... \t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(3000);
        Console.WriteLine("In Main end... \t\t{0} {1}", (DateTime.Now.Ticks - ticks) / TimeSpan.TicksPerMillisecond, Thread.CurrentThread.ManagedThreadId);
    }

    private static Int64 ticks;
}

结果如下:

enter image description here

也许我不完全理解等待到底是什么。我认为如果执行进入等待状态,那么执行将返回到调用者方法和等待另一个线程中运行的任务。在我的示例中,所有操作都在一个线程中执行,并且在 wait 关键字之后执行不会返回到调用方方法。 真相在哪里?


这不是这样的async-await works.

将方法标记为async不创建任何后台线程。当您致电async方法它同步运行直到异步点,然后才返回给调用者。

那个异步点是当你await尚未完成的任务。当它完成时,该方法的其余部分将被安排执行。该任务应该代表一个实际的异步操作(如 I/O,或Task.Delay).

在您的代码中没有异步点,也没有返回调用线程的点。线程会越陷越深并阻塞Thread.Sleep直到这些方法完成并且DoAsync返回。

举这个简单的例子:

public static void Main()
{
    MainAsync().Wait();
}

public async Task MainAsync()
{
    // calling thread
    await Task.Delay(1000);
    // different ThreadPool thread
}

这里我们有一个实际的异步点(Task.Delay) 调用线程返回到Main然后同步阻塞该任务。一秒钟后Task.Delay任务完成,方法的其余部分在不同的上执行ThreadPool线。

如果代替Task.Delay我们会用Thread.Sleep那么它将全部运行在同一个调用线程上。

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

C# async/await 控制台应用程序中的奇怪行为 的相关文章

  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • WCF 中 SOAP 消息的数字签名

    我在 4 0 中有一个 WCF 服务 我需要向 SOAP 响应添加数字签名 我不太确定实际上应该如何完成 我相信响应应该类似于下面的链接中显示的内容 https spaces internet2 edu display ISWG Signe
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 使用 x509 证书签署 json 文档或字符串

    如何使用 x509 证书签署 json 文档或字符串 public static void fund string filePath C Users VIKAS Desktop Data xml Read the file XmlDocum
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低

随机推荐

  • MATLAB 中的 SVM 可视化

    在 Matlab 中执行 SVM 训练后 如何可视化 SVM 分类 到目前为止 我只用以下方法训练了 SVM Labels are 1 or 1 groundTruth Ytrain d xtrain model svmtrain grou
  • 如何创建 JSON 数组?

    你好 我想创建一个 JSON 数组 我尝试过使用 JSONArray jArray new JSONArray while itr hasNext int objId itr next jArray put objId odao getOb
  • 带参数的 Java Webstart

    我可以启动一个Java网络启动具有一组参数的应用程序就像使用 标签配置小程序一样 Thanks 是的 您可以 下面显示了一个示例
  • HTML5/JS - 启动多个网络工作者

    我目前正在编写一个程序 我必须处理巨大的数组 但是我可以拆分这些数组 我现在的计划是 在不同的网络工作者中处理数组 然而 我从未与他们合作过 并且确实有几个问题 1 我将如何运行多个网络工作者 我尝试了一个看起来像这样的 for 循环 fo
  • Angular 如何测试@HostListener

    我有以下指令 当应用于输入元素时 它会检查字符并在禁止字符时调用 PreventDefault Directive selector cdtPreventInput export class PreventInputDirective im
  • 从google帐户获取用户名、头像

    我正在开发一个使用 GoogleAccountCredential 登录 上传和下载文件到 GoogleDrive 的模块 我想让谷歌帐户的用户名 姓氏和头像显示在我的登录功能上 I ve try GoogleAccountCredenti
  • 使 ASP.NET WCF 将字典转换为 JSON,省略“Key”和“Value”标签

    这是我的困境 我正在使用 RESTful ASP NET 服务 尝试获取一个函数来返回以下格式的 JSON 字符串 Test1Key Test1Value Test2Key Test2Value Test3Key Test3Value 但我
  • Python变量是指针吗?或者说,它们是什么?

    据我所知 Python 中的变量只是指针 根据这条规则 我可以假设此代码片段的结果 i 5 j i j 3 print i 将会3 但我得到了一个令我意想不到的结果 那就是5 此外 我的 Python 书确实介绍了这个示例 i 1 2 3
  • 不需要的双导航栏

    当我点击屏幕时 我使导航栏 顶部栏 出现 消失 并且也位于背景图像的顶部 它有效 但有一个问题 我突然有两个导航栏 首先 有一个名为 后退 的后退按钮 当我按 后退 时 它会弹出一个新的导航栏 其中有一个名为 Vinene 的后退按钮 这是
  • glClear(GL_COLOR_BUFFER_BIT) 后 OpenGL 无效帧缓冲区操作;

    每次我打电话后glClear GL COLOR BUFFER BIT 我收到 OpenGL 错误 无效的帧缓冲区操作 通话似乎工作正常 没有任何问题 我打电话glClear GL COLOR BUFFER BIT 第一件事在 paintGL
  • 这个规范的集群示例是如何工作的?

    当必须通过文件系统同步程序 shell脚本 时 我发现了一种flock基于的解决方案是受到推崇的 也应该工作on NFS 在脚本中使用的规范示例 来自http linux die net man 1 flock is flock s 200
  • C# 中的 URL Slugify 算法?

    所以我搜索并浏览了slug标记 SO 并只找到两个引人注目的解决方案 C 中的 Slugify 和字符转写 如何在 C 中将上标或下标转换为普通文本 这只是问题的部分解决方案 我可以自己手动编写代码 但令我惊讶的是还没有解决方案 那么 C
  • 大约持续 2 秒后出现“设备上没有剩余空间”的信息EMR m1.large 实例上有 10 GB 数据

    当我使用 m1 large 作为作业流要创建的 hadoop 实例的实例类型来运行 Amazon EMR 作业时 我收到错误 设备上没有剩余空间 该工作产生约 最大 10 GB 数据 因为 m1 large 实例的容量应该为 420GB 2
  • 有没有办法使用 EF Core 映射复杂类型

    EF Core 不支持复杂类型映射 如果我有一个对象 例如 public class Entity public string StringProp get set public SubEntity NestedEntity get set
  • 如何获取当前用户目录?

    使用这个 Environment GetFolderPath Environment SpecialFolder ApplicationData 我得到这个输出 C Documents and Settings USER Applicati
  • GIT:在新/脏/开发分支中将更改提交到旧/安全分支,而不检出或丢失未暂存的数据

    在开始进行实验性开发之前 我创建了一个新分支 我通常会忘记这一点 这不是问题 但现在我提前做了 从那时起我已经更新了3个文件 2 中只是实验性更改 我不想将其提交到安全分支 在 1 中只是安全 较小的 更改 我绝对希望将其提交到安全分支 我
  • 在 PostgreSQL 中将 bytea 表示为单个整数的最简单方法是什么?

    我有一个bytea包含 14 字节数据的列 14 个字节的最后 3 个字节包含数据的 CRC 码 我想将 CRC 提取为单个整数以存储在新列中 我该怎么做呢 为了澄清这一点 下面是在 Java 中执行此操作的一种方法 int crc raw
  • 翻转绘制文本/字符串的 GraphicsPath

    我的文本类中有这个方法 但我似乎无法翻转整个文本 我正在使用矩阵来变换GraphicsPath用于绘制字符串 这是我使用 Jimi 的答案后的代码 public LayerClass DrawString LayerClass Type t
  • ClassNotFoundException 与 NoClassDefFoundError 与无法找到或加载主类 XYZ 之间有什么区别?

    我探索了多个站点 但实际上无法理解它们之间的区别 我想知道三个站点之间的确切区别 A NoClassDefFoundError如果类文件引用了一个在运行时找不到但在编译时可用的类 则会抛出此错误 来源 https docs oracle c
  • C# async/await 控制台应用程序中的奇怪行为

    我构建了一些异步 等待演示控制台应用程序并得到了奇怪的结果 代码 class Program public static void BeginLongIO Action act Console WriteLine In BeginLongI