调用t.SetResult()时C#多任务的执行逻辑及线程相关问题
问题解答
1. 调用t.SetResult();时会发生什么?
调用SetResult会完成TaskCompletionSource对应的Task(即t.Task)。所有等待这个Task的代码——也就是四个Run方法里的await requisite;——会结束等待,它们后续的Console.WriteLine(text);会被调度执行。这些后续代码会在异步上下文(控制台程序中为线程池)里调度,不会阻塞当前调用SetResult的线程。
2. 这段代码是否为多线程执行?
是多线程执行。原因如下:
await Task.Delay(1000)会释放当前线程,后续的t.SetResult();和Console.WriteLine("End");会在线程池线程上恢复执行;- 当
t.SetResult()完成任务后,四个Run方法的输出代码会被分别调度到线程池的不同线程(或同一线程,但调度顺序由线程池决定)执行,和执行End的线程形成多线程并行。
3. 控制台输出的内容顺序是否有保证?
没有任何顺序保证:
Console.WriteLine("End")是在t.SetResult()之后同步执行,但四个Run方法的输出是异步调度的,所以End可能在A/B/C/D之前或之后输出;- A、B、C、D的输出顺序也不确定,因为四个任务的后续代码由线程池并行调度,线程池的执行顺序无法预测,谁先抢到线程谁先输出。
4. 若Run方法修改List<>集合,是否需要考虑多线程安全问题?
需要。List<>本身不是线程安全的集合,当多个线程同时对它进行修改(如Add、Remove)或读写操作时,会导致数据损坏、索引越界异常等问题。必须通过加锁(比如lock语句)或者使用线程安全的集合(如ConcurrentBag<T>、ConcurrentQueue<T>)来保证线程安全。
内容的提问来源于stack exchange,提问作者Everton Elvio Koser
相关产品推荐
相关产品推荐

