从同步函数返回任务与空隙

发布于 2025-02-03 12:14:44 字数 801 浏览 4 评论 0原文


I am just curious about a scenario around returning a `Task` vs `void` from a synchronous function. Given I have a function, as below, that can either return a Task or a void. I am just curious if there is any benefit in returning a `Task` rather than just a `void`?

public void SynchronousFunction(/* some input */) { /* some synchronous operation */}

// VS 

public Task SynchronousFunction(/* some input */)
{
    /* some synchronous operation */
    return Task.CompletedTask
}

// VS Variation of Task return function

public Task SynchronousFunction(/* some input */)
{      
   return Task.Run(() => /* some synchronous operation */
}

我的观点是两个折。首先,感觉像返回任务需要一些不必要的拳击和拆箱,其次,如果在某些同步代码中调用函数,则不需要使用.wait()或类似的东西来调用。

I am just curious about a scenario around returning a `Task` vs `void` from a synchronous function. Given I have a function, as below, that can either return a Task or a void. I am just curious if there is any benefit in returning a `Task` rather than just a `void`?


public void SynchronousFunction(/* some input */) { /* some synchronous operation */}

// VS 

public Task SynchronousFunction(/* some input */)
{
    /* some synchronous operation */
    return Task.CompletedTask
}

// VS Variation of Task return function

public Task SynchronousFunction(/* some input */)
{      
   return Task.Run(() => /* some synchronous operation */
}

My view is two fold. Firstly, it feels like returning a Task would require some unnecessary boxing and unboxing, and, secondly, if the function gets called in some synchronous code it doesn't need to be called with .Wait() or such like thing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

画中仙 2025-02-10 12:14:44

在第一个示例中,您的代码同步执行。呼叫线程调用该方法被阻止,等待方法执行在执行其他任何操作之前完成。

在某些情况下,这很好(例如,您需要运行的一些脚本过程以维护数据库),在其他情况下,这是一个问题(例如,在控制器代码中的ASP.NET核心应用程序中的服务器端代码)。

第二个示例基本上是相同的,但是您正在返回完成的任务。代码仍然同步完成,没有区别。呼叫者恢复了已经完成的任务对象。等待该任务的任何形式(同步等待wait()方法或异步等待async关键字)立即完成,因为任务>代码>对象已经完成。
没有拳击行为,因为任务是参考类型。相反,由于您正在创建参考类型的实例(查看task.pletedTask的文档。换句话说,这不是缓存的实例)。

请注意,此方法签名对于方法呼叫者有些混乱:它可能认为此方法正在执行I/O工作,但实际上它在做CPU绑定的工作。您应该清楚地记录这种行为,甚至更好地避免使用此签名。

在第三个示例中,您要求线程池进行一些工作,然后返回任务对象,代表您已卸载到线程池的正在进行的操作。 任务对象基本上是一个代理,您可以用来等待分配给线程池的工作负载。

当方法返回时,您只是知道您已经要求线程池去做某件事,何时以及如何完成工作完全由运行时控制。呼叫代码通常等待完成任务。可以通过阻止线程(例如wait())或在不阻止线程的情况下同步完成此操作(例如等待)

In the first example your code executes synchronously. The calling thread calling the method is blocked, waiting for the method execution to complete before doing anything else.

In some cases this is fine (e.g. some scripting procedure you need to run in order to maintain a database), some other times this is an issue (e.g. server side code inside an ASP.NET core application in the controller code).

The second example is basically the same, but you are instead returning a completed task. The code still completes synchronously, there is no difference. The caller gets back an already completed task object. Any form of waiting on that Task (both synchronous wait with the Wait() method or asynchronous wait with the async keyword) completes immediately, because the Task object is already completed.
There is no boxing behavior involved, because Task is a reference type. There is instead allocation, because you are creating an instance of a reference type (check out the docs for Task.CompletedTask. They clearly say that calling it multiple times is not guaranteed to always return the same instance, in other words it is not a cached instance).

Notice that this method signature is somewhat confusing for the method caller: it may think that this method is doing I/O work, but it is actually doing CPU bound work. You should clearly document this behavior or even better avoid this signature at all if you can.

In the third example you are asking the thread pool to do some work, and you are returning a Task object representing the ongoing operation that you have offloaded to the thread pool. The Task object is basically a proxy that you can use to wait for the completion of the workload you have assigned to the thread pool.

When the method returns you simply know that you have asked the thread pool to do something, when and how this work is done is totally under the control of the runtime. Calling code typically waits for the task to be completed. This can be done synchronously, by blocking the thread (e.g. Wait()) or asynchronously without blocking the thread (e.g. await)

清泪尽 2025-02-10 12:14:44

在方法之外,应避免使用异步返回空隙,您不会在异步空隙方法中发现任何例外。

Returning void with async should be avoided cause outside of the method you will not catch any exceptions happening in async void method.

未央 2025-02-10 12:14:44

这取决于用法,如果您必须在其中调用一些异步操作,例如向API或DB提出请求,您可以具有async Task或或async void。通常,异步只允许呼叫底部的任务在等待您的方法执行时没有任何变化。

public Task SynchronousFunctionAsync(/* some input */)
{
    return Task.CompletedTask; 
    // This method allows you to start new Task if you need
}

public async Task SynchronousFunctionAsync(/* some input */)
{      
    await Task.CompletedTask;
    // This method allows you to await some other operations
}

public async void SynchronousFunction(/* some input */)
{      
    await Task.CompletedTask;
    // This method also allows you to await some other operations
    // but by calling it can't be awaited.
}

It depends on the usage, if you have to call some async operations in it like making request to an API or DB you can eighter have async Task or async void. Usually async just allows the tasks in the bottom of your call to be awaited nothing changes in the execution of your methods.

public Task SynchronousFunctionAsync(/* some input */)
{
    return Task.CompletedTask; 
    // This method allows you to start new Task if you need
}

public async Task SynchronousFunctionAsync(/* some input */)
{      
    await Task.CompletedTask;
    // This method allows you to await some other operations
}

public async void SynchronousFunction(/* some input */)
{      
    await Task.CompletedTask;
    // This method also allows you to await some other operations
    // but by calling it can't be awaited.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文