C# 如果我的接口必须返回任务,那么实现无操作的最佳方法是什么?

C# 如果我的接口必须返回任务,那么实现无操作的最佳方法是什么?,c#,.net,task-parallel-library,async-await,threadpool,C#,.net,Task Parallel Library,Async Await,Threadpool,在下面的代码中,由于接口的原因,类LazyBar必须从其方法返回一个任务(并且为了参数的缘故不能更改)。如果LazyBars实现不寻常,因为它恰好快速同步运行-从方法返回无操作任务的最佳方式是什么 我已经使用了下面的Task.Delay(0),但是我想知道如果函数被多次调用(为了参数起见,比如说每秒数百次),这是否会对性能产生任何副作用: 这是不是有什么大问题 它开始阻塞我的应用程序的线程池了吗 编译器解理器是否足以以不同方式处理延迟(0) 将返回Task.Run(()=>{})有什么不同吗

在下面的代码中,由于接口的原因,类
LazyBar
必须从其方法返回一个任务(并且为了参数的缘故不能更改)。如果
LazyBar
s实现不寻常,因为它恰好快速同步运行-从方法返回无操作任务的最佳方式是什么

我已经使用了下面的
Task.Delay(0)
,但是我想知道如果函数被多次调用(为了参数起见,比如说每秒数百次),这是否会对性能产生任何副作用:

  • 这是不是有什么大问题
  • 它开始阻塞我的应用程序的线程池了吗
  • 编译器解理器是否足以以不同方式处理
    延迟(0)
  • 返回Task.Run(()=>{})有什么不同吗
有更好的办法吗

using System.Threading.Tasks;

namespace MyAsyncTest
{
    internal interface IFooFace
    {
        Task WillBeLongRunningAsyncInTheMajorityOfImplementations();
    }

    /// <summary>
    /// An implementation, that unlike most cases, will not have a long-running
    /// operation in 'WillBeLongRunningAsyncInTheMajorityOfImplementations'
    /// </summary>
    internal class LazyBar : IFooFace
    {
        #region IFooFace Members

        public Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
        {
            // First, do something really quick
            var x = 1;

            // Can't return 'null' here! Does 'Task.Delay(0)' have any performance considerations?
            // Is it a real no-op, or if I call this a lot, will it adversely affect the
            // underlying thread-pool? Better way?
            return Task.Delay(0);

            // Any different?
            // return Task.Run(() => { });

            // If my task returned something, I would do:
            // return Task.FromResult<int>(12345);
        }

        #endregion
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            Test();
        }

        private static async void Test()
        {
            IFooFace foo = FactoryCreate();
            await foo.WillBeLongRunningAsyncInTheMajorityOfImplementations();
            return;
        }

        private static IFooFace FactoryCreate()
        {
            return new LazyBar();
        }
    }
}
使用System.Threading.Tasks;
名称空间MyAsyncTest
{
内部接口IFooFace
{
任务将在大多数实现中异步运行();
}
/// 
///与大多数情况不同的是,实现不会具有长期运行的性能
///“将在大多数实现中运行异步”中的操作
/// 
内部类LazyBar:IFooFace
{
#区域IFooFace成员
公共任务将在大多数实现()中异步运行
{
//首先,做一些非常快的事情
var x=1;
//此处无法返回“null”!任务延迟(0)是否有任何性能考虑因素?
//这是一个真正的无操作,或者如果我称之为很多,它会对环境产生不利影响吗
//底层线程池?更好的方法?
返回任务。延迟(0);
//有什么不同吗?
//返回Task.Run(()=>{});
//如果我的任务有结果,我会:
//返回任务.FromResult(12345);
}
#端区
}
内部课程计划
{
私有静态void Main(字符串[]args)
{
Test();
}
专用静态异步无效测试()
{
IFooFace foo=FactoryCreate();
等待foo.willbelong在大多数实现中运行异步();
返回;
}
私有静态IFooFace FactoryCreate()
{
返回新的LazyBar();
}
}
}

今天,我建议使用来完成此任务


.net 4.6之前版本:

使用
Task.FromResult(0)
Task.FromResult(null)
将比使用无运算表达式创建
Task
产生更少的开销。在使用预先确定的结果创建
任务时,不涉及调度开销。

要添加关于使用
任务的内容,请从result
,如果缓存已完成的任务,则可以进一步提高性能,因为已完成任务的所有实例都相同:

public static class TaskExtensions
{
    public static readonly Task CompletedTask = Task.FromResult(false);
}
使用
TaskExtensions.CompletedTask
可以在整个应用程序域中使用相同的实例


只添加了static属性

Task completedTask = Task.CompletedTask;
Task.Delay(0)
在接受的答案中是一个很好的方法,因为它是已完成的
任务的缓存副本

从4.6开始,现在有了
Task.CompletedTask
,它的目的更加明确,但不仅仅是
Task.Delay(0)
仍然返回单个缓存实例,它返回与
Task.CompletedTask
相同的单个缓存实例


两者的缓存性质都不能保证保持不变,但作为依赖于实现的优化,它们仅作为依赖于实现的优化(也就是说,如果实现更改为仍然有效的内容,它们仍然可以正常工作)使用
Task.Delay(0)
比公认的答案要好。

我更喜欢
任务完成任务=Task.completedTask解决方案,但另一种方法是将该方法标记为async并返回void:

    public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
    {
    }

您将收到一个警告(CS1998-不带等待表达式的异步函数),但在本上下文中可以安全地忽略此警告。

最近遇到此问题,并不断收到有关方法无效的警告/错误

我们的工作是安抚编译器,这就清除了它:

    public async Task MyVoidAsyncMethod()
    {
        await Task.CompletedTask;
    }

这是迄今为止所有建议中最好的一个。除非您在方法中实际执行某些操作,否则不需要返回语句。

当您必须返回指定类型时:

Task.FromResult<MyClass>(null);
Task.FromResult(空);

如果您使用泛型,所有答案都会给我们提供编译错误。您可以使用
返回默认值(T)。下面的示例将进一步解释

public async Task<T> GetItemAsync<T>(string id)
            {
                try
                {
                    var response = await this._container.ReadItemAsync<T>(id, new PartitionKey(id));
                    return response.Resource;
                }
                catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
                {

                    return default(T);
                }

            }
公共异步任务GetItemAsync(字符串id) { 尝试 { var response=等待此消息。_container.ReadItemAsync(id,new PartitionKey(id)); 返回响应资源; } 当(ex.StatusCode==System.Net.HttpStatusCode.NotFound)时捕获(CosmosException ex) { 返回默认值(T); } }
相关问题:就个人而言,我会选择
Task.FromResult(null)
。如果您碰巧使用它们,则会提供一个TaskConstants类来提供这些已完成的任务以及其他一些非常有用的任务(0 int,true/false,Default())
返回默认值(YourReturnType)
@图例无法直接创建任务我不确定,但是
任务。CompletedTask
可能会成功!(但需要.NET4.6)我需要退回还是等待?@Pixar你是什么意思?您可以同时执行这两项操作,但等待操作将同步进行。抱歉,我不得不提到上下文:)在我现在看到的情况下,我们可以使
公共任务在大多数实现()中异步运行()
<
public async Task<T> GetItemAsync<T>(string id)
            {
                try
                {
                    var response = await this._container.ReadItemAsync<T>(id, new PartitionKey(id));
                    return response.Resource;
                }
                catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
                {

                    return default(T);
                }

            }
return await Task.FromResult(new MyClass());