gpt4 book ai didi

c# - 是否可以更改异步方法的任务创建选项?

转载 作者:行者123 更新时间:2023-11-30 19:53:41 25 4
gpt4 key购买 nike

我有一个异步方法,我想为其提供 TaskCreationOptions.LongRunning 标志。使用包装 Task 调用的非异步方法很容易:

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

或许多变体中的任何一个(Task.Run、new Task 等)。但是,似乎没有办法将方法定义为异步并返回 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 返回后在线程池线程中执行。按照正常情况,它会在调用线程上被调用,但之后不会尝试在调用线程上恢复执行。

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

最佳答案

There Is No Thread

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

async 方法只有在等待其他 异步操作时才是异步的。就这样。只有在这些操作作为实际线程(例如 Task.Run())启动的情况下,才会有一个线程被描述为长时间运行,并且在那如果您可以在调用 Task.Run() 时访问所需的选项。

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

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

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

关于c# - 是否可以更改异步方法的任务创建选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47025731/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com