Does await really does Task.Run()

29 浏览
0 Comments

Does await really does Task.Run()

我仍在努力完全理解async/await的方法。有人能告诉我,就像主题中所说的,await真的会在后台执行Task.Run吗?有时人们在包含await的异步方法中使用Task.Run,但有时也有人在没有异步方法的情况下使用Task.Run。哪种方式是正确的?

0
0 Comments

await的背后并不使用Task.Run。

await不仅仅适用于Task.Run。它用于在某个操作完成后运行代码。这个操作可以是使用Task.Run创建的计算任务,也可以是数据检索,比如使用ReadLineAsync。Task是用来模拟所有这些操作的类。

Task.Run用于将工作排队到线程池中运行。这在编写CPU密集型代码时是合适的,但在处理IO密集型操作时不应使用Task.Run。在这种情况下,您的异步代码(可能使用async/await)应该使用异步IO方法,如WriteLineAsync和前面提到的ReadLineAsync。

在工作线程上运行阻塞代码使用Task.Run是一个反模式。即使它解除了GUI线程的阻塞,也不应该这样做。

有时,人们在异步方法中使用await,但有时也会看到人们在没有异步方法的情况下使用Task.Run。哪种方式才是正确的?

确实可以使用Task.Run创建一个任务,然后让它自行运行,而不使用await或ContinueWith。这些被称为“fire and forget”任务。它们很少是一个好主意。与使用await不同,该任务抛出的任何异常都将丢失。

这个问题在Stephen Cleary的StackOverflow回答中有解释。

0
0 Comments

在使用async和await时,我们经常会遇到一个问题:是否真的需要在Task.Run()方法上使用await操作符。这个问题的出现是因为async操作符只是在方法中启用了await操作符的使用。而await操作符可以用于任何可等待的对象。在.NET中,Task和Task<T>就是一些可等待的对象的例子。

Task.Run()方法返回Task对象,Task.Run<T>()方法返回Task<T>对象,正如我所说的,它们都是可等待的对象,所以你可以在它们上面使用await操作符。

如果你愿意,你甚至可以自己编写一个可等待的类型:你只需要确保满足被认为是可等待的要求。一个可等待的类型需要提供GetAwaiter的实现就可以了。下面是一个可等待的示例:

public struct SimpleInt32Awaitable 
{ 
    public SimpleInt32Awaiter GetAwaiter() 
    { 
        return new SimpleInt32Awaiter(); 
    } 
}
public struct SimpleInt32Awaiter 
{ 
    public bool IsCompleted { get { return true; } }
    public void OnCompleted(Action continuation) 
    { 
    }
    public int GetResult() 
    { 
        return 5; 
    } 
}

现在你可以这样做:

// 在其他某个类中
static async void SimpleWaitAsync() 
{ 
    SimpleInt32Awaitable awaitable = new SimpleInt32Awaitable(); 
    int result = await awaitable; 
} 

所以,回到最初的问题:是否真的需要在Task.Run()方法上使用await操作符?答案是取决于具体情况。如果你想在异步操作中执行一些计算密集型的工作,并且不希望阻塞主线程,那么在Task.Run()上使用await是有意义的。但是,如果你只是想在异步操作中执行一些简单的工作,而不需要等待它完成,那么在Task.Run()上使用await是没有必要的。

0
0 Comments

async await并不是用来执行Task.Run或启动新线程的,它仅仅是为了让代码在某些阻塞的情况下继续执行。

问题的出现是因为有人可能误解了async await的功能,认为它可以执行Task.Run或启动新线程。在上述链接中的博客中有一个很好的解释,可以解决这个误解。

解决方法是通过阅读上述链接中的博客文章,了解async await的真正功能和用法。在理解了async await的原理之后,就不会错误地期望它能够执行Task.Run或启动新线程了。

0