gpt4 book ai didi

c# - `Task` 上下文可以在其第一个 `await` 之前切换吗?

转载 作者:太空狗 更新时间:2023-10-29 23:59:39 26 4
gpt4 key购买 nike

Task的创建是上下文切换点,还是只有开始await或者做其他异步事情的时候?

例如,如果我有这些功能:

async Task Foo()
{
Console.WriteLine("In Foo");
await bar();
}

void CallFoo()
{
var task = Foo();
Console.WriteLine("Returned from Foo");
task.Wait();
}

是否可以在“In Foo”之前打印“Returned from Foo”?

最佳答案

Is it possible for "Returned from Foo" to print before "In Foo"?

在您编写的程序中,不,那是不可能的。

如果您有一个运行工作线程的不同程序,那么您就会遇到线程间排序副作用的所有常见问题。 “async/await”并没有什么特别之处可以解决这些问题。

Is the creation of a Task a context switching point, or only when it starts to await or do other asynchronous things?

让我们更准确地说明“上下文切换点”的含义。

C# 中的方法可以执行以下四种操作之一:

  • 永远奔跑
  • 正常返回
  • throw
  • 暂停——我认为您所说的“上下文切换”就是这个意思。

标记为 async 的方法可以挂起,但它们仅在 await 一个未完成的可等待对象时挂起。等待已完成的可等待对象不会挂起,但它可以抛出。

async 方法返回的任务热门。也就是说,异步工作流开始并运行直到它返回、抛出或挂起。可以使用 Task 构造函数创建一个“冷”任务,直到您对其调用 Start 时它才会开始。通常您不会这样做,除非您正在编写自己的任务调度程序。

请注意,这与迭代器 block 不同。一个常见的错误是:

IEnumerable<int> GetMeSomeInts(int x) 
{
if (x < 0)
throw new SomeException();
for (int i = 0; i < x; i += i)
yield return i;
}

如果你说

var nums = GetMeSomeInts(-1); // 1
foreach(int num in nums) // 2
...

那么throw不会发生在第1行,而是发生在第2行!当您调用迭代器 block 时,不会运行到第一个 yield。它们会立即挂起并且不会执行,直到在 foreach 中迭代。要小心,尤其是当您在同一个程序中同时使用异步和迭代器协程时。

关于c# - `Task` 上下文可以在其第一个 `await` 之前切换吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52671558/

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