.Net 任务 class - 请解释
.Net Task class - please explain
有人可以解释为什么下面的 public async Task DoStuff() 方法在没有 return 任何东西的情况下仍然可以工作吗?它没有说 void,所以我假设 return 类型必须是 Task。
当我从 DoStuff() 方法中删除 async 和 await 关键字时,编译器给我一个 "not all code paths return a value" 错误。但是,如果我添加 async 和 await 关键字,它似乎不需要 return 类型,尽管方法签名中缺少 void 关键字。我不明白!
究竟什么是任务?微软对此的解释非常糟糕。谢谢
namespace Async_and_Await_Example
{
class Program
{
static void Main(string[] args)
{
AsyncAwaitDemo demo = new AsyncAwaitDemo();
demo.DoStuff();
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Working on the Main Thread...................");
}
}
}
public class AsyncAwaitDemo
{
public async Task DoStuff()
{
await Task.Run(() =>
{
CountToFifty();
});
}
private static async Task<string> CountToFifty()
{
int counter;
for (counter = 0; counter < 51; counter++)
{
Console.WriteLine("BG thread: " + counter);
}
return "Counter = " + counter;
}
}
}
这是因为 async/await
很神奇。好吧,这并不是真的神奇,但是对于 async/await
,编译器正在重写您的方法,以便它 return 成为 Task
。就像 CountToFifty()
returns a Task<string>
但是你的方法 returns a string
.
一个Task
本身没什么特别的。它只是一个普通的 .Net class,用于表示可能尚未完成的操作。
如果没有 async/await,编译器不会修改 DoStuff()
,因此您可以 return 一个 Task 对象。
一个任务本质上是一个 promise (or future). It “promises” you that the asynchronous method you started will eventually finish, completing the task. The task object is used so that you can get information about when the task is done. There is also the generic version 任务,它也简单地承诺在任务完成时你会得到一个值。
启动异步方法后,您会得到一个 Task
对象。该方法 return 几乎立即生效,但实际工作可能会稍后完成。然后,您可以 wait 等待任务完成以阻塞当前线程并简单地等待异步方法完成。
当您自己处于异步执行中时(这通常是您在调用异步方法时想要执行的操作),那么您可以使用 await 这些任务 await
任务对象上的关键字。这实质上会暂停您当前所在的异步方法,并在您等待的任务完成后立即执行 return。
await
关键字仅在异步方法中可用,由 async
方法说明符发出信号。这些方法将自动 return 为 return 值的任务对象:如果您不 return 异步方法中的任何内容,它 return 是 Task
目的;如果您 return 来自异步方法的 T
类型的对象,它实际上 return 是一个您可以等待的 Task<T>
对象。 Task<T>
类型可以在任务完成后“解包”。这允许您获取 T
.
类型的实际对象
最后,async
方法也可以 return 什么都没有,void
,让它们“即发即忘”。如果你调用一个 return 类型为 void
的异步方法,它将被异步执行(“fire”)但你无法知道它何时完成,因为你没有任务要等待的对象(“忘记”)。这就是为什么您通常要避免使用 async void
方法(它们也不利于异常处理)并始终使用“真正的”可等待异步方法(那些 return 某些任务对象)。但是您仍然可以使用 async void
方法来启动异步执行 而不会阻塞您的主线程 。否则,您可以通过在任务上调用 Wait()
方法来阻止它。
有关详细信息,请查看以下链接:
因为异步方法不会立即 return。一个方法可能需要查询一个外部源。这需要时间——其他代码可以 运行。这就是方法中 await-async 的目的。因此,当我们使用 await 关键字时,并不总是需要在异步方法中 return。
检查 Explanation of Tasks by DotNetPearls 了解更多。
Why the public async Task DoStuff() method below can still work without returning anything?
因为编译器允许。当您使用 async
修饰符标记方法时,会创建一个状态机,它实际上为您 returns 一个 Task
。你可以在任何反编译器中看到它。
When I remove the async and await keywords from the DoStuff() method, the compiler gives me a "not all code paths return a value" error.
因为不再创建 returns 和 Task
的状态机,你现在必须自己做,因为没有更多的编译器魔法。
What exactly IS a Task?
正如其他人所说,只是对未来将完成的工作的承诺。一个Task
可以代表很多东西,其中之一就是异步操作。魔法在于旁边的 async-await
关键字。编译器魔法与 Task
有着特殊的关系,但可以等待任何实现 GetAwaiter
方法的类型。更多相关信息 here
正如其他人指出的那样,任务是 "promise" 或 "future" - 也就是说,它代表将来可能完成的一些操作。
Task
表示没有return值的操作,Task<T>
表示return值为T
.
的操作
请注意 Task
很有用(而不是 void
),因为该操作可能成功完成或出现异常(或取消),并且 Task
能够表示这些最终状态。
Can someone please explain why the public async Task DoStuff() method below can still work without returning anything?
async
关键字将为您的方法构造一个状态机,状态机将创建一个代表该方法的Task
对象。如果您的 async
方法 return 是一个值,状态机会将该 return 值放在 Task<T>
上。如果您的 async
方法抛出异常,状态机会将异常置于 Task
/Task<T>
.
What exactly IS a Task?
我已经在 async
/await
的上下文中描述了 Task
是什么。部分混淆是因为 Task
在以其他方式使用时具有非常不同的含义。我对异步任务使用术语 Promise Task,对 code-运行 任务使用 Delegate Task。
由 async
状态机创建的任务始终是 Promise 任务。一般来说,异步任务应该await
'ed,而不是Wait
'ed。并且您应该避免 async void
(因为状态机无法表示该方法,它具有令人惊讶的异常处理语义)。
你可能会找到我的 async
intro helpful as well as my article on best practices.
另一种看待这个问题的方式是假设您有 4 件事要做以响应来自客户的 http 请求。
- 在数据库中输入订单。 Task.Run(下单)
- 向客户发送感谢邮件。 Task.Run(发送电子邮件)
- 向您的运营中心发送请求 api。 Task.Run(下单)
- 记录会话请求。 Task.Run(日志请求)
因此,与其谈论合同、承诺、状态服务器等,不如说任务是将工作分散到所有 cores/processors 上的线程。我有 4 个内核和 8 个处理器。如果我执行上述任务,我可以看到所有 8 个处理器都在运行,而且速度是原来的两倍多。这是一个任务。
它变得更好了。现在所有 8 个处理器上的工作是 运行,但我们可以让它更快。尽管他们在所有 8 个处理器上都是 运行,但他们轮流或排队等待对方完成。假设每个任务平均需要 5 秒,所以我对客户的响应时间是 20 秒,但我们只是将其减半。如果我使用 async/await,我可以同时推送所有 4 个任务,因此 none 个任务会互相等待。所以现在我可以看到所有 8 个处理器都在运行,但现在它们使用了更多 cpu 和 wow64 它们完成了。
但是等等,他们仍然很慢,因为 api 发送订单的请求需要 8 秒,客户和其他任务必须等待它完成。这是它变得非常好的地方。别等了。回复客户并感谢他们的订单。所以现在您只需 3 毫秒而不是 20 秒就可以将交易返回给客户。将 try/catch 包裹在 4 个任务周围并记录任何失败,以便有人可以处理它们。希望这已经完成,而不是告诉客户哦,对不起,我们的邮件服务器已关闭。我听到一些人称那是忘记和其他东西,这非常糟糕。不算太差。这是很好的编程。坚实的主流 threading/asynchronous 编程早就应该了。购买从未使用过的核心和内存以及处理响应缓慢的用户坦率地等待他们不关心的事情将有望成为过去。
这是任务/async/await。
var myTask = Task.Run(() => { doSomething });。
有人可以解释为什么下面的 public async Task DoStuff() 方法在没有 return 任何东西的情况下仍然可以工作吗?它没有说 void,所以我假设 return 类型必须是 Task。
当我从 DoStuff() 方法中删除 async 和 await 关键字时,编译器给我一个 "not all code paths return a value" 错误。但是,如果我添加 async 和 await 关键字,它似乎不需要 return 类型,尽管方法签名中缺少 void 关键字。我不明白!
究竟什么是任务?微软对此的解释非常糟糕。谢谢
namespace Async_and_Await_Example
{
class Program
{
static void Main(string[] args)
{
AsyncAwaitDemo demo = new AsyncAwaitDemo();
demo.DoStuff();
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Working on the Main Thread...................");
}
}
}
public class AsyncAwaitDemo
{
public async Task DoStuff()
{
await Task.Run(() =>
{
CountToFifty();
});
}
private static async Task<string> CountToFifty()
{
int counter;
for (counter = 0; counter < 51; counter++)
{
Console.WriteLine("BG thread: " + counter);
}
return "Counter = " + counter;
}
}
}
这是因为 async/await
很神奇。好吧,这并不是真的神奇,但是对于 async/await
,编译器正在重写您的方法,以便它 return 成为 Task
。就像 CountToFifty()
returns a Task<string>
但是你的方法 returns a string
.
一个Task
本身没什么特别的。它只是一个普通的 .Net class,用于表示可能尚未完成的操作。
如果没有 async/await,编译器不会修改 DoStuff()
,因此您可以 return 一个 Task 对象。
一个任务本质上是一个 promise (or future). It “promises” you that the asynchronous method you started will eventually finish, completing the task. The task object is used so that you can get information about when the task is done. There is also the generic version 任务,它也简单地承诺在任务完成时你会得到一个值。
启动异步方法后,您会得到一个 Task
对象。该方法 return 几乎立即生效,但实际工作可能会稍后完成。然后,您可以 wait 等待任务完成以阻塞当前线程并简单地等待异步方法完成。
当您自己处于异步执行中时(这通常是您在调用异步方法时想要执行的操作),那么您可以使用 await 这些任务 await
任务对象上的关键字。这实质上会暂停您当前所在的异步方法,并在您等待的任务完成后立即执行 return。
await
关键字仅在异步方法中可用,由 async
方法说明符发出信号。这些方法将自动 return 为 return 值的任务对象:如果您不 return 异步方法中的任何内容,它 return 是 Task
目的;如果您 return 来自异步方法的 T
类型的对象,它实际上 return 是一个您可以等待的 Task<T>
对象。 Task<T>
类型可以在任务完成后“解包”。这允许您获取 T
.
最后,async
方法也可以 return 什么都没有,void
,让它们“即发即忘”。如果你调用一个 return 类型为 void
的异步方法,它将被异步执行(“fire”)但你无法知道它何时完成,因为你没有任务要等待的对象(“忘记”)。这就是为什么您通常要避免使用 async void
方法(它们也不利于异常处理)并始终使用“真正的”可等待异步方法(那些 return 某些任务对象)。但是您仍然可以使用 async void
方法来启动异步执行 而不会阻塞您的主线程 。否则,您可以通过在任务上调用 Wait()
方法来阻止它。
有关详细信息,请查看以下链接:
因为异步方法不会立即 return。一个方法可能需要查询一个外部源。这需要时间——其他代码可以 运行。这就是方法中 await-async 的目的。因此,当我们使用 await 关键字时,并不总是需要在异步方法中 return。
检查 Explanation of Tasks by DotNetPearls 了解更多。
Why the public async Task DoStuff() method below can still work without returning anything?
因为编译器允许。当您使用 async
修饰符标记方法时,会创建一个状态机,它实际上为您 returns 一个 Task
。你可以在任何反编译器中看到它。
When I remove the async and await keywords from the DoStuff() method, the compiler gives me a "not all code paths return a value" error.
因为不再创建 returns 和 Task
的状态机,你现在必须自己做,因为没有更多的编译器魔法。
What exactly IS a Task?
正如其他人所说,只是对未来将完成的工作的承诺。一个Task
可以代表很多东西,其中之一就是异步操作。魔法在于旁边的 async-await
关键字。编译器魔法与 Task
有着特殊的关系,但可以等待任何实现 GetAwaiter
方法的类型。更多相关信息 here
正如其他人指出的那样,任务是 "promise" 或 "future" - 也就是说,它代表将来可能完成的一些操作。
Task
表示没有return值的操作,Task<T>
表示return值为T
.
请注意 Task
很有用(而不是 void
),因为该操作可能成功完成或出现异常(或取消),并且 Task
能够表示这些最终状态。
Can someone please explain why the public async Task DoStuff() method below can still work without returning anything?
async
关键字将为您的方法构造一个状态机,状态机将创建一个代表该方法的Task
对象。如果您的 async
方法 return 是一个值,状态机会将该 return 值放在 Task<T>
上。如果您的 async
方法抛出异常,状态机会将异常置于 Task
/Task<T>
.
What exactly IS a Task?
我已经在 async
/await
的上下文中描述了 Task
是什么。部分混淆是因为 Task
在以其他方式使用时具有非常不同的含义。我对异步任务使用术语 Promise Task,对 code-运行 任务使用 Delegate Task。
由 async
状态机创建的任务始终是 Promise 任务。一般来说,异步任务应该await
'ed,而不是Wait
'ed。并且您应该避免 async void
(因为状态机无法表示该方法,它具有令人惊讶的异常处理语义)。
你可能会找到我的 async
intro helpful as well as my article on best practices.
另一种看待这个问题的方式是假设您有 4 件事要做以响应来自客户的 http 请求。
- 在数据库中输入订单。 Task.Run(下单)
- 向客户发送感谢邮件。 Task.Run(发送电子邮件)
- 向您的运营中心发送请求 api。 Task.Run(下单)
- 记录会话请求。 Task.Run(日志请求)
因此,与其谈论合同、承诺、状态服务器等,不如说任务是将工作分散到所有 cores/processors 上的线程。我有 4 个内核和 8 个处理器。如果我执行上述任务,我可以看到所有 8 个处理器都在运行,而且速度是原来的两倍多。这是一个任务。
它变得更好了。现在所有 8 个处理器上的工作是 运行,但我们可以让它更快。尽管他们在所有 8 个处理器上都是 运行,但他们轮流或排队等待对方完成。假设每个任务平均需要 5 秒,所以我对客户的响应时间是 20 秒,但我们只是将其减半。如果我使用 async/await,我可以同时推送所有 4 个任务,因此 none 个任务会互相等待。所以现在我可以看到所有 8 个处理器都在运行,但现在它们使用了更多 cpu 和 wow64 它们完成了。
但是等等,他们仍然很慢,因为 api 发送订单的请求需要 8 秒,客户和其他任务必须等待它完成。这是它变得非常好的地方。别等了。回复客户并感谢他们的订单。所以现在您只需 3 毫秒而不是 20 秒就可以将交易返回给客户。将 try/catch 包裹在 4 个任务周围并记录任何失败,以便有人可以处理它们。希望这已经完成,而不是告诉客户哦,对不起,我们的邮件服务器已关闭。我听到一些人称那是忘记和其他东西,这非常糟糕。不算太差。这是很好的编程。坚实的主流 threading/asynchronous 编程早就应该了。购买从未使用过的核心和内存以及处理响应缓慢的用户坦率地等待他们不关心的事情将有望成为过去。
这是任务/async/await。
var myTask = Task.Run(() => { doSomething });。