【问题标题】:Is it possible to change the task creation options of an async method?是否可以更改异步方法的任务创建选项?
【发布时间】:2017-10-30 23:28:22
【问题描述】:

我有一个异步方法,我想提供 TaskCreationOptions.LongRunning 标志。这很容易通过包装 Task 调用的非异步方法来实现:

void Foo() { Thread.Sleep(5000); }
var task = Task.Factory.StartNew(Foo, TaskCreationOptions.LongRunning);
Console.WriteLine(task.CreationOptions);
// LongRunning

或多种变体中的任何一种(Task.Run、新任务等)。但是,似乎没有办法将方法定义为异步并返回Task

async Task FooAsync() { await Task.Delay(TimeSpan.FromSeconds(10.0)); }
Task fooTask = FooAsync();
Console.WriteLine(FooTask.CreationOptions);
// None

尝试将其包装在长时间运行的任务中也是一个空启动器:

async Task FooAsync() { await Task.Delay(TimeSpan.FromSeconds(10.0)); }
Task<Task> wrapTask = Task.Factory.StartNew(FooAsync, TaskCreationOptions.LongRunning);
Console.WriteLine(wrapTask.CreationOptions);
// LongRunning
Console.WriteLine(wrapTask.Unwrap().CreationOptions);
// None

在这种情况下,wrapTask 确实是LongRunning,但它几乎立即返回(在FooAsync 调用await Task.Delay(...) 之后不久),因此设置该标志实际上可能是不可取的。我最终想要等待的是wrapTask.Unwrap()

在我的测试中我发现,事实上,FooAsync 中的代码在从await 返回后在线程池线程中执行。正常情况下,它在调用线程上调用,但之后不会尝试在调用线程上恢复执行。

我希望这可以通过方法属性来控制,但我找不到任何可以在这里提供帮助的东西。是否可以更改编译器为异步方法生成的创建选项?尝试一下有意义吗?

【问题讨论】:

    标签: c# .net async-await


    【解决方案1】:

    There Is No Thread

    您的问题没有任何意义,因为async 方法不是线程。它不启动线程,不代表线程,与线程没有任何有用的关系。

    async 方法仅在它等待其他异步操作的范围内是异步的。就这样。只有在这些操作作为实际线程启动的情况下(例如Task.Run())才会有一个线程来描述为长时间运行,在这种情况下,您可以访问您想要的选项,当您拨打Task.Run()时。

    如果您的async 方法本身实际上是长期运行的,那么为什么首先要创建async 方法呢?您可以仅通过同步等待其他异步操作来保持线程。恕我直言,这并不理想,但您已经接受了您将在很长一段时间内保留该线程,那么为什么不更长呢?

    或者,也许您只是表示等待可能需要很长时间。在这种情况下,使用选项LongRunning 甚至是不正确的,因为这告诉调度程序您的操作将在较长时间内保持线程。您的抱怨似乎是“代码......在从await 返回后在线程池线程中执行”。但是您的代码在等待时实际上并没有持有线程,因此它并没有真正长时间运行。

    如果在通过await 产生线程之前,您的方法中有 确实 实际运行了较长时间的元素,并且您不想阻塞当前线程以等待方法,那么在我看来,您应该将async 方法的那些部分重构为它们自己的方法,您可以通过Task.Run() 执行这些方法。然后,您的 async 方法可以等待那些不阻塞当前线程,并且您可以向线程调度程序指示操作的那些特定部分 长时间运行(即通过将选项传递给Task.Run())。

    【讨论】:

    • +1 表示“您的代码在等待时实际上并没有持有线程,所以它并不是真正长时间运行” - 真的总结了整个事情
    猜你喜欢
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-16
    • 1970-01-01
    • 2016-04-24
    相关资源
    最近更新 更多