在另一个线程中运行异步函数

2024-03-20

我正在评估异步 CTP。

如何开始在另一个线程池的线程上执行异步函数?

static async Task Test()
{
    // Do something, await something
}

static void Main( string[] args )
{
    // Is there more elegant way to write the line below?
    var t = TaskEx.Run( () => Test().Wait() );

    // Doing much more in this same thread
    t.Wait(); // Waiting for much more then just this single task, this is just an example
}

我是 Stack Overflow 的新手(我的第一篇文章),但我很高兴您询问有关异步 CTP 的问题,因为我是 Microsoft 团队中的一员:)

我想我明白你的目标是什么,并且你正在做一些正确的事情来帮助你实现目标。

我认为你想要什么:

static async Task Test()
{
    // Do something, await something
}

static void Main(string[] args)
{
    // In the CTP, use Task.RunEx(...) to run an Async Method or Async Lambda
    // on the .NET thread pool
    var t = TaskEx.RunEx(Test);
    // the above was just shorthand for
    var t = TaskEx.RunEx(new Func<Task>(Test));
    // because the C# auto-wraps methods into delegates for you.

    // Doing much more in this same thread
    t.Wait(); // Waiting for much more then just this single task, this is just an example
}

Task.Run 与 Task.RunEx

因为此 CTP 安装在 .NET 4.0 之上,所以我们不想修补actual System.Threading.Tasks.Task输入 mscorlib。相反,当 Playground API 发生冲突时,它们会被命名为 FooEx。

为什么我们给其中一些命名Run(...)和一些RunEx(...)?原因是我们发布 CTP 时尚未完成方法重载的重新设计。在我们当前的工作代码库中,我们实际上必须稍微调整 C# 方法重载规则,以便 Async Lambda 发生正确的事情 - 它可以返回void, Task, or Task<T>.

问题是当异步方法或 lambda 返回时Task or Task<T>,它们实际上在返回表达式中没有外部任务类型,因为任务是作为方法或 lambda 调用的一部分自动为您生成的。在我们看来,这似乎是代码清晰性的正确体验,尽管这确实使事情变得非常不同,因为通常 return 语句的表达式可以直接转换为方法或 lambda 的返回类型。

因此,两者都是异步的voidlambda 和异步Tasklambda 支持return;没有争论。因此,需要对方法重载决策进行澄清,以决定选择哪一个。因此,同时拥有 Run(...) 和 RunEx(...) 的唯一原因是,我们可以确保在 PDC 2010 到来时为异步 CTP 的其他部分提供更高质量的支持。


如何考虑异步方法/lambda

我不确定这是否是一个混淆点,但我想我应该提到这一点 - 当您编写异步方法或异步 lambda 时,它可以呈现调用它的人的某些特征。这是基于两件事:

  • 您正在等待的类型
  • 可能还有同步上下文(取决于上面)

wait 的 CTP 设计和我们当前的内部设计都非常基于模式,因此 API 提供商可以帮助充实一组您可以“等待”的充满活力的事物。这可能会根据您正在等待的类型而有所不同,常见的类型是Task.

Task的await实现非常合理,并且遵循当前线程的SynchronizationContext决定如何推迟工作。如果您已经处于 WinForms 或 WPF 消息循环中,那么您的延迟执行将在同一消息循环中返回(就像您使用BeginInvoke()“你的方法的其余部分”)。如果您等待一个任务并且您已经在 .NET 线程池上,那么“方法的其余部分”将在其中一个线程池线程(但不一定是完全相同的线程)上恢复,因为它们一开始就被池化并且您很可能很乐意使用第一个可用的池线程。


使用 Wait() 方法的注意事项

在您的示例中您使用了:var t = TaskEx.Run( () => Test().Wait() );

其作用是:

  1. 在周围线程中同步调用 TaskEx.Run(...) 在线程池上执行 lambda。
  2. 为 lambda 指定一个线程池线程,它调用您的异步方法。
  3. 异步方法 Test() 是从 lambda 调用的。因为 lambda 是在线程池上执行的,所以 Test() 内的任何延续都可以在线程池中的任何线程上运行。
  4. lambda 实际上并没有腾出该线程的堆栈,因为它没有等待。在这种情况下,TPL 的行为取决于 Test() 是否在 Wait() 调用之前实际完成。但是,在这种情况下,当线程池线程等待 Test() 在另一个线程上完成执行时,您很可能会阻塞该线程。

这是“await”运算符的主要好处是它允许您添加稍后执行的代码 - 但不会阻塞原始线程。在线程池的情况下,可以实现更好的线程利用率。

如果您对 VB 或 C# 的异步 CTP 有其他疑问,请告诉我,我很乐意听听:)

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

在另一个线程中运行异步函数 的相关文章

随机推荐

  • 与 Swingworker 的对话是先有鸡还是先有蛋

    我试图遵循 Java 最佳实践 不在主线程 EDT 上执行长时间任务 所以我计划使用带有模态对话框的 swingWorker 这样 模式对话框会阻止用户执行任何操作 直到该任务完成 并且我可以在该过程发生时更新对话框上的状态 现在的问题是
  • 清理docker环境:devicemapper

    我有一个包含 2 个容器的 docker 环境 Jenkins 和 Nexus 都有自己的命名卷 我每天都有一个 cron 作业 它会删除未使用的容器和图像 这工作正常 但问题出在我的 devicemapper 内部 du sh var l
  • MKMapView 注释更改/丢失顺序?

    我有一个带有注释的地图视图 这些注释显示标注 单击标注的公开详细信息按钮时 它会进入一个新视图 我的 MKAnnotations 是一个自定义类 它实现
  • iOS 9 / Xcode 7:SKSpriteNode spriteNodeWithImageNamed 在某些设备上不起作用

    我在从 SKSpriteNode 的 xcassets 图像集中加载图像时遇到问题 虽然它在 iOS 8 x 上运行良好 SKSpriteNode spriteNodeWithImageNamde 图像名称 它不适用于某些运行 iOS 9
  • 引用限定成员函数作为模板参数?

    这在 clang 3 3 中编译得很好 template
  • 如何重新搜索或重新匹配整个文件而不将其全部读入内存?

    我希望能够对整个文件运行正则表达式 但我希望不必立即将整个文件读入内存 因为将来我可能会处理相当大的文件 有没有办法做到这一点 谢谢 澄清 我无法逐行阅读 因为它可以跨越多行 您可以使用 mmap 将文件映射到内存 然后可以像普通字符串一样
  • Next.js 中传递动态路由的无效参数时如何返回 404 Not Found 页面和 HTTP 状态?

    例如 我有一条动态路线 blog article id 访问现有博客文章时 blog id that exist 它按预期工作 现在我要处理这个案例 blog id that does not exist适当地 代码在 blog id js
  • R 中的条件交叉表

    寻找使用 expss 包实现以下任务的最快方法 有了一个很棒的 expss 包 我们可以轻松地进行交叉表 它具有其他优点和交叉表的有用功能 我们可以轻松地对多个变量进行交叉表 如下所示 install packages expss libr
  • 将 dbml 中的连接字符串指向 app.config

    我可以直接将连接字符串指向Dbml designer cs到连接字符串app conf 我编写了下面的代码 它成功指向app config public leDataContext base ConfigurationManager Con
  • Htaccess - 重定向除一个网址之外的所有网址

    我正在尝试将所有网址从一个域重定向到另一个域 但一个 某种 这是我必须重定向的 htaccess 除了域之外 都保持相同的 url 例如 domain com something 转到domain2 com something Rewrit
  • boost C++ 无锁队列与共享队列

    我对多线程编程很陌生 我只知道最常见的生产者 消费者 队列 我正在使用 boost c 库 我不知道是否更好地使用 boost lockfree queue 或使用 mutex 和 condition variable 的 std queu
  • Me 关键字的行为不一致

    我注意到的行为MeVBA 代码中的关键字模板文件根据文档是否具有 ActiveX 控件而有所不同 带有 ActiveX 控件的文档 Me引用从模板创建的新文件 没有 ActiveX 控件的文档 Me引用模板而不是新文件 为了演示这种奇怪的行
  • Windows 控制台中的希腊字母

    我正在用 C 编写一个程序 当我在 cmd exe 中运行它时 我希望在菜单中包含希腊字符 有人说 为了包含希腊字符 你必须使用printf事情是这样的 printf charset IS0 1089 uffe 但他们不确定 有谁知道这是怎
  • 西里尔字母验证

    今天我遇到了一个有趣的缺陷 问题是我在俄罗斯部署了我的 Web 应用程序 并且名称值 在下面的方法中没有返回 true 作为字母数字 很好奇人们如何解决这样的问题 邓肯 private boolean isAlphaNumeric Stri
  • 在长按手势识别器上获取错误的 UIButton 标签

    我知道已经有很多类似的问题被问到 但我已经尝试了所有这些问题 并且在未能解决我的问题时我发布了我的问题 首先我尝试的问题是 1 如何通过longPressGestureRecognizer获取button tag https stackov
  • 将自签名 XAP 部署到 Windows Phone 8

    我们为 WP8 开发了一个应用程序 并希望通过 XAP 文件的下载 URL 在内部分发它 到目前为止我们已采取的步骤 使用Makecert exe生成带有XXX pvk的自签名XXX cer 无密码 使用 Pvk2Pfx exe 创建一个包
  • jquery ajax加载覆盖插件[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 没有 Sql Alchemy 引擎的 Dataframe 到 sql

    我有一个数据框 id value name 1 100 sam 2 766 abc 3 234 qqq 4 435 ppp 5 345 mmm 我想将此表保存到 SQL Server 数据库表 tab1 中 我可以df to sql 但当我
  • 在特定日期使用 CSS 更改背景?

    有谁知道如何在特定日期使用 CSS 自动更改网站的背景 比如情人节 复活节 圣诞节等 为此 您必须使用 PHP 或 JavaScript 等服务器端语言 例如 使用 PHP 您可以使用以下命令访问服务器日期 时间date http php
  • 在另一个线程中运行异步函数

    我正在评估异步 CTP 如何开始在另一个线程池的线程上执行异步函数 static async Task Test Do something await something static void Main string args Is th