【发布时间】:2022-01-23 15:57:06
【问题描述】:
我正在使用一些 asyncio Python 代码,但遇到了协程排序问题。我对 C# 有一定的经验,所以我会用它作为例子。
在 C# 中我可以编写:
using System;
using System.Threading.Tasks;
public class Program
{
async static Task<int> foo(int n, int delay)
{
Console.WriteLine("Foo start {0}",n);
await Task.Delay(delay);
Console.WriteLine("Foo end {0}",n);
return 0;
}
public static void Main()
{
Task<int> t1 = foo(1,300);
Task<int> t2 = foo(2,200);
Task.WaitAll(new []{t2,t1});// Reverse on purpose
}
}
结果如下,注意协程的开始匹配调用顺序,不是等待顺序。这是由于协程函数如何划分到生成器中而得到保证的。 IE。它们总是同步运行,直到第一个 await。
Foo start 1
Foo start 2
Foo end 2
Foo end 1
但是当我在 Python 中做同样的事情时,我会得到不同的顺序。
import asyncio
async def foo(n,delay):
print(f"Foo start {n}")
await asyncio.sleep(delay/1000)
print(f"Foo end {n}")
return 0
async def main():
t1 = foo(1,300)
t2 = foo(2,200)
await asyncio.gather(t2,t1) # Reverse on purpose
asyncio.run(main())
Foo start 2
Foo start 1
Foo end 2
Foo end 1
我也知道这是为什么 - 因为 foo(1,300) 返回一个生成器,它在协程等待/调度之前不会启动。
我的问题是如何在 Python 中实现类似 C# 的行为,这意味着协程在调用它们时开始而不会中断,直到第一个 await?
我试过了
t1 = asyncio.create_task(foo(1,300))
t2 = asyncio.create_task(foo(2,200))
哪个解决了问题,但调度顺序真的有保证吗?
【问题讨论】:
标签: python c# python-asyncio