c# - Task.Yield() 与 Task.Delay(0)

标签 c# .net multithreading task-parallel-library async-await

Delay(0) 是否总是内联?根据我的经验,它确实:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication
{
    class Program
    {
        static async Task Test()
        {
            await Task.Yield();
            Console.WriteLine("after Yield(), thread: {0}", Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(0);
            Console.WriteLine("after Delay(0), thread: {0}", Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(100);
            Console.WriteLine("after Delay(100), thread: {0}", Thread.CurrentThread.ManagedThreadId);
        }
        static void Main(string[] args)
        {
            Console.WriteLine("Main thread: {0}", Thread.CurrentThread.ManagedThreadId);
            Test().Wait();
        }
    }
}

这是一个控制台应用程序,因此线程池用于延续。输出:

Main thread: 11
after Yield(), thread: 7
after Delay(0), thread: 7
after Delay(100), thread: 6

最佳答案

Task.Delay 中,它看起来像这样(单个参数 (int) 版本只是调用以下版本):

[__DynamicallyInvokable]
public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
{
    if (millisecondsDelay < -1)
    {
        throw new ArgumentOutOfRangeException("millisecondsDelay", Environment.GetResourceString("Task_Delay_InvalidMillisecondsDelay"));
    }
    if (cancellationToken.IsCancellationRequested)
    {
        return FromCancellation(cancellationToken);
    }
    if (millisecondsDelay == 0)
    {
        return CompletedTask;
    }
    DelayPromise state = new DelayPromise(cancellationToken);
    if (cancellationToken.CanBeCanceled)
    {
        state.Registration = cancellationToken.InternalRegisterWithoutEC(delegate (object state) {
            ((DelayPromise) state).Complete();
        }, state);
    }
    if (millisecondsDelay != -1)
    {
        state.Timer = new Timer(delegate (object state) {
            ((DelayPromise) state).Complete();
        }, state, millisecondsDelay, -1);
        state.Timer.KeepRootedWhileScheduled();
    }
    return state;
}

正如您希望看到的那样:

    if (millisecondsDelay == 0)
    {
        return CompletedTask;
    }

这意味着它总是返回一个已完成的任务,因此您的代码将始终继续运行到特定的 await 行。

关于c# - Task.Yield() 与 Task.Delay(0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18527149/

相关文章:

c# - 使用 async 和 await 回调

.net - .NET Remoting 中出现 "Tcp channel protocol violation expecting preamble"的原因是什么?

c# - MS Dynamics CRM 插件错误 - [A]CrmWebSvc 无法转换为 [B]CrmWebSvc

c# - 使用新名称从 .bak 文件恢复数据库

multithreading - boost::asio 中的动态线程池示例

multithreading - 如果可以动态获取锁,则强加锁顺序并不能保证防止死锁。这是什么意思?

c# - 为什么此 DateTime.ParseExact 调用失败?

c# - 如何删除因意外双击按钮而生成的函数?

c# - WPF BitmapFrame 和多线程

c# - 无法加载文件或程序集 'WebGrease, Version=1.5.1.25624, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 或其依赖项之一