一个人应该在另一个Task中使用Task.Run吗? [英] Should one use Task.Run within another Task?

查看:89
本文介绍了一个人应该在另一个Task中使用Task.Run吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Task中,我有很多工作要做(CPU约束或IO约束,没有异步接口可使用).我想知道是否可以在这样的任务中完成所有非异步工作:

I have a bunch of work to do (either CPU-bound or IO-bound with no async interface to use) within a Task. I'm wondering if it's OK to just do all the non-async work within the task like this:

async Task DoSomeStuff()
{
    await SomethingAsync();
    …
    DoCpuBoundWork();
    …
    await SomethingElseAsync();
}

还是应该使用Task.Run这样?

or should I use Task.Run like this?

async Task DoSomeStuff()
{
    await SomethingAsync();
    …
    await Task.Run(() => DoCpuBoundWork());
    …
    await SomethingElseAsync();
}

我知道任务不一定要在另一个线程上执行,所以我想知道调度程序是否可以假设任务是非阻塞的,这将使Task之外的CPU绑定工作运行..例如,如果调度程序决定将CPU绑定的工作调度到应用程序的UI线程,则可能会降低速度.

I know tasks aren't necessarily executed on another thread, so I'm wondering if the scheduler might make assumptions about tasks being non-blocking that'll make doing CPU-bound work outside of Task.Run slow the application down. For example, if the scheduler decided to schedule the CPU-bound work to the app's UI thread, there could be a slow-down.

我可以肯定已经问过这个问题了,但是我找不到合适的关键词来搜索,所以对此感到抱歉.

I'm certain this question's been asked before, but I can't find the right keywords to search for it, so sorry about that.

推荐答案

此页面(深入了解任务和任务< T>,了解如何执行CPU约束操作),任务在调用它们的线程上运行,并且CPU约束的工作确实应该被包装在 Task.Run 中,以便它将在另一个(后台)线程上运行.因此,是的,在异步方法中使用Task.Run进行CPU绑定或阻塞工作是正常的,这是正常的.从页面引用:

As noted in this page (section Deeper Dive into Task and Task<T> for a CPU-Bound Operation), tasks run on the thread from which they're called, and CPU-bound work should indeed be wrapped in a Task.Run so it'll run on another (background) thread. So yes, it's OK and normal to use Task.Run within an async method for CPU-bound or otherwise blocking work. Quoted from the page:

public async Task<int> CalculateResult(InputData data)
{
    // This queues up the work on the threadpool.
    var expensiveResultTask = Task.Run(() => DoExpensiveCalculation(data));

    // Note that at this point, you can do some other work concurrently,
    // as CalculateResult() is still executing!

    // Execution of CalculateResult is yielded here!
    var result = await expensiveResultTask;

    return result;
}

CalculateResult()在调用它的线程上执行.当它调用Task.Run时,它将在线程池上排队昂贵的CPU绑定操作DoExpensiveCalculation(),并接收一个Task句柄.DoExpensiveCalculation()最终会在下一个可用线程(可能在另一个CPU内核)上同时运行.在另一个线程上DoExpensiveCalculation()繁忙时,可以执行并发工作,因为调用CalculateResult()的线程仍在执行.

CalculateResult() executes on the thread it was called on. When it calls Task.Run, it queues the expensive CPU-bound operation, DoExpensiveCalculation(), on the thread pool and receives a Task handle. DoExpensiveCalculation() is eventually run concurrently on the next available thread, likely on another CPU core. It's possible to do concurrent work while DoExpensiveCalculation() is busy on another thread, because the thread which called CalculateResult() is still executing.

一旦遇到等待,就会将CalculateResult()的执行交给其调用方,从而允许在DoExpensiveCalculation()产生结果时使用当前线程完成其他工作.完成后,结果将排队等待在主线程上运行.最终,主线程将返回执行CalculateResult(),这时它将具有DoExpensiveCalculation()的结果.

Once await is encountered, the execution of CalculateResult() is yielded to its caller, allowing other work to be done with the current thread while DoExpensiveCalculation() is churning out a result. Once it has finished, the result is queued up to run on the main thread. Eventually, the main thread will return to executing CalculateResult(), at which point it will have the result of DoExpensiveCalculation().

这篇关于一个人应该在另一个Task中使用Task.Run吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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