Task.Yield()与Task.Delay(0) [英] Task.Yield() versus Task.Delay(0)

查看:776
本文介绍了Task.Yield()与Task.Delay(0)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确实延迟(0)总要得到内联?根据我的经验,它的作用:

 使用系统;
使用的System.Threading;
使用System.Threading.Tasks;

命名空间ConsoleApplication
{
    类节目
    {
        静态异步任务测试()
        {
            等待Task.Yield();
            Console.WriteLine(后的产率(),螺纹:{0},Thread.CurrentThread.ManagedThreadId);
            等待Task.Delay(0);
            Console.WriteLine(后的延迟(0),螺纹:{0},Thread.CurrentThread.ManagedThreadId);
            等待Task.Delay(100);
            Console.WriteLine(后的延迟(100),螺纹:{0},Thread.CurrentThread.ManagedThreadId);
        }
        静态无效的主要(字串[] args)
        {
            Console.WriteLine(主要思路:{0},Thread.CurrentThread.ManagedThreadId);
            。测试()等待();
        }
    }
}
 

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

 主线程:11
后的产率(),螺纹:7
后延迟(0),螺纹:7
后延迟(100),螺纹:6
 

解决方案

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

  [__ DynamicallyInvokable]
公共静态任务延迟(INT millisecondsDelay,的CancellationToken的CancellationToken)
{
    如果(millisecondsDelay< -1)
    {
        抛出新ArgumentOutOfRangeException(millisecondsDelay,Environment.GetResourceString(Task_Delay_InvalidMillisecondsDelay));
    }
    如果(cancellationToken.IsCancellationRequested)
    {
        返回FromCancellation(的CancellationToken);
    }
    如果(millisecondsDelay == 0)
    {
        返回CompletedTask;
    }
    DelayPromise状态=新DelayPromise(的CancellationToken);
    如果(cancellationToken.CanBeCanceled)
    {
        state.Registration = cancellationToken.InternalRegisterWithoutEC(委托(对象状态){
            ((DelayPromise)状态).Complete();
        }, 州);
    }
    如果(millisecondsDelay!= -1)
    {
        state.Timer =新的定时器(委托(对象状态){
            ((DelayPromise)状态).Complete();
        },州,millisecondsDelay,-1);
        state.Timer.KeepRootedWhileScheduled();
    }
    返回的状态;
}
 

正如你所希望看到:

 如果(millisecondsDelay == 0)
    {
        返回CompletedTask;
    }
 

这意味着它总是返回一个完成的任务,因此,您的code将一如既往地继续过去那种特定的运行计谋行。

Does Delay(0) always get inlined? In my experience, it does:

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();
        }
    }
}

This is a console app, thus the thread pool is used for continuation. The output:

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

解决方案

Inside Task.Delay, it looks like this (the single parameter (int) version just calls the below version):

[__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;
}

As you can hopefully see:

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

Which means it always returns a completed task, and therefore your code will always continue running past that particular await line.

这篇关于Task.Yield()与Task.Delay(0)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆