有没有像这样编写方法的场景:
public async Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return await DoAnotherThingAsync();
}
Run Code Online (Sandbox Code Playgroud)
而不是这个:
public Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return DoAnotherThingAsync();
}
Run Code Online (Sandbox Code Playgroud)
会有意义吗?
为什么return await在可以直接Task<T>从内部DoAnotherThingAsync()调用返回时使用构造?
我return await在很多地方看到代码,我想我应该错过一些东西.但据我了解,在这种情况下不使用async/await关键字并直接返回Task将在功能上等效.为什么要增加附加await层的额外开销?
快问...
为了对异步编程有一些基础的了解,await我想知道这两个代码片段在多线程和执行顺序和时间方面有什么区别:
这个:
public Task CloseApp()
{
return Task.Run(
()=>{
// save database
// turn off some lights
// shutdown application
});
}
Run Code Online (Sandbox Code Playgroud)
对此:
public async Task CloseApp()
{
await Task.Run(
()=>{
// save database
// turn off some lights
// shutdown application
});
}
Run Code Online (Sandbox Code Playgroud)
如果我在这个例程中调用它:
private async void closeButtonTask()
{
// Some Task 1
// ..
await CloseApp();
// Some Task 2
// ..
}
Run Code Online (Sandbox Code Playgroud) 我有一个界面
interface IFoo
{
Task<Bar> CreateBarAsync();
}
Run Code Online (Sandbox Code Playgroud)
有两种方法可以创建Bar,一种是异步,另一种是同步.我想为这两种方法中的每一种提供接口实现.
对于异步方法,实现可能如下所示:
class Foo1 : IFoo
{
async Task<Bar> CreateBarAsync()
{
return await AsynchronousBarCreatorAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我该如何实现Foo2使用同步方法创建的类Bar?
我可以实现同步运行的方法:
async Task<Bar> CreateBarAsync()
{
return SynchronousBarCreator();
}
Run Code Online (Sandbox Code Playgroud)
然后,编译器将警告不要async在方法签名中使用:
这种异步方法缺少"等待"运算符并将同步运行.考虑使用'await'运算符等待非阻塞API调用,或'await Task.Run(...)'在后台线程上执行CPU绑定工作.
或者,我可以实现显式返回的方法Task<Bar>.在我看来,代码看起来不那么可读:
Task<Bar> CreateBarAsync()
{
return Task.Run(() => SynchronousBarCreator());
}
Run Code Online (Sandbox Code Playgroud)
从性能的角度来看,我认为这两种方法的开销大致相同,或者?
我应该选择哪种方法; async同步实现方法或显式包装同步方法调用Task?
编辑
我正在开发的项目实际上是一个.NET 4项目,其中包含来自Microsoft Async NuGet包的async/await扩展.在.NET 4上,可以替换为.我有意识地在上面的例子中使用了.NET 4.5方法,希望能让主要问题更加清晰.Task.RunTaskEx.Run
在任务返回异步方法结束时,如果我调用另一个异步方法,我可以使用await它或return它的任务.每个的后果是什么?
Task FooAsync()
{
return BazAsync(); // Option A
}
async Task BarAsync()
{
await BazAsync(); // Option B
}
Run Code Online (Sandbox Code Playgroud) 根据这个讨论,以下两种方法应该没有区别:
public async Task Foo()
{
await DoSomethingAsync();
}
public Task Foo()
{
return DoSomethingAsync();
}
Run Code Online (Sandbox Code Playgroud)
实际上,似乎对于非常简单的方法,没有 async/await关键字的调用将是首选,因为它们会消除一些开销.
然而,这显然并不总是在单元测试中起作用.
MSTest的
[TestClass]
public class AsyncTest
{
[TestMethod]
public async Task Test1()
{
await Task.Delay(0);
}
[TestMethod]
public Task Test2()
{
return Task.Delay(0);
}
}
Run Code Online (Sandbox Code Playgroud)
NUnit的
[TestFixture]
public class AsyncTest
{
[Test]
public async Task Test1()
{
await Task.Delay(0);
}
[Test]
public Task Test2()
{
return Task.Delay(0);
}
}
Run Code Online (Sandbox Code Playgroud)
的xUnit
public class AsyncTest
{
[Fact]
public async Task Test1() …Run Code Online (Sandbox Code Playgroud) 此代码抛出异常.是否可以定义将捕获它的应用程序全局处理程序?
string x = await DoSomethingAsync();
Run Code Online (Sandbox Code Playgroud)
使用.net 4.5/WPF
C#提供了两种创建异步方法的方法:
方法1:
static Task<string> MyAsyncTPL() {
Task<string> result = PerformWork();
return result.ContinueWith(t => MyContinuation());
}
Run Code Online (Sandbox Code Playgroud)
方法2:
static async Task<string> MyAsync() {
string result = await PerformWork();
return MyContinuation();
}
Run Code Online (Sandbox Code Playgroud)
上述两种方法都是异步的并且实现了同样的目的.那么,我什么时候应该选择一种方法呢?使用其中一个是否有任何指导方针或优点?
为简单起见,我们假设我们有一个方法应该在执行一些繁重的操作时返回一个对象.有两种实现方式:
public Task<object> Foo()
{
return Task.Run(() =>
{
// some heavy synchronous stuff.
return new object();
}
}
Run Code Online (Sandbox Code Playgroud)
和
public async Task<object> Foo()
{
return await Task.Run(() =>
{
// some heavy stuff
return new object();
}
}
Run Code Online (Sandbox Code Playgroud)
在检查生成的IL之后,生成了两个完全不同的东西:
.method public hidebysig
instance class [mscorlib]System.Threading.Tasks.Task`1<object> Foo () cil managed
{
// Method begins at RVA 0x2050
// Code size 42 (0x2a)
.maxstack 2
.locals init (
[0] class [mscorlib]System.Threading.Tasks.Task`1<object>
)
IL_0000: nop
IL_0001: ldsfld class [mscorlib]System.Func`1<object> AsyncTest.Class1/'<>c'::'<>9__0_0'
IL_0006: dup …Run Code Online (Sandbox Code Playgroud) 我最近一直在处理异步等待(阅读包括Stephen和Jon最后两章在内的所有可能的文章),但我得出结论,我不知道它是否100%正确. - 因此我的问题.
由于 async只允许单词等待出现,我将async不谈.
AFAIU等待着继续.而不是编写功能(连续)代码,编写同步代码.(我想把它称为可回调代码)
因此,当编译器到达时await- 它将代码分成2个部分,并在第一部分完成后注册要执行的第二部分(我不知道为什么callback不使用该字- 这正是所做的).(同时工作 - 线程回来做其他事情).
但看看这段代码:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
string st= await workTask;
//do something with st
}
public Task <string> SimulateWork()
{
return ...
}
Run Code Online (Sandbox Code Playgroud)
当线程到达时await workTask;,将方法拆分为2个部分.所以在SimulateWork完成之后 - 方法的继续:AKA://do something with st- 被执行.
一切都好
但是,如果方法是:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
await workTask; //i …Run Code Online (Sandbox Code Playgroud) 对于在Unity中专门研究此难题的人来说,这很重要,
请确保看到我问的另一个问题,它提出了相关的关键问题:
对于C#专家,Unity是单线程的1
在另一个线程上进行计算等是很常见的。
当您在另一个线程上执行某些操作时,您经常会使用async / wait,因为,所有优秀的C#程序员都说这是简单的方法!
void TankExplodes() {
ShowExplosion(); .. ordinary Unity thread
SoundEffects(); .. ordinary Unity thread
SendExplosionInfo(); .. it goes to another thread. let's use 'async/wait'
}
using System.Net.WebSockets;
async void SendExplosionInfo() {
cws = new ClientWebSocket();
try {
await cws.ConnectAsync(u, CancellationToken.None);
...
Scene.NewsFromServer("done!"); // class function to go back to main tread
}
catch (Exception e) { ... }
}
Run Code Online (Sandbox Code Playgroud)
好的,因此,当您执行此操作时,在Unity / C#中以更常规的方式启动线程时,您将“照常做” (例如,使用Thread或其他方法,或者让本机插件执行它,或使用OS或其他方法)可能是这样)。
一切都很好。
作为一个la脚的Unity程序员,他只知道足够的C#来结束一天,我一直认为 …
c# ×10
async-await ×7
.net ×6
asynchronous ×4
.net-4.5 ×1
c#-5.0 ×1
clr ×1
exception ×1
mstest ×1
nunit ×1
task ×1
unit-testing ×1