包括Lambda在内的异步/等待方法的正确方法
本文关键字:方法 等待 异步 Lambda 包括 | 更新日期: 2023-09-27 18:28:59
我想展示两种关于异步编程的范例,并听取您的意见。
A
假设您已经在库中创建了一个类似以下的方法,以便从GUI客户端使用它。
public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
TestObject testObj = new TestObject();
...fill in params to testObj...
await MethodCallAsync(testObj);
....do other work synchronous.....
....continue fill testObj properties...
await Task.Delay(1000) // just a delay for no reason
...continue synchronous work.....
return testObj;
}
好吧,但这会把我的GUI上下文分割成几个小的调用块,对吧?或者我不知道从你声明一个方法async的那一刻起,它是否会为里面的所有操作创建一个Task?
如果是的话,那就太好了,没问题,我们可以宣布它是异步的,然后继续我们的生活。
让我们说不,我想采取以下方法,这样我就不会干扰GUI,直到我的整个方法调用完成并得到结果,所以在我的调用方法中做点什么。
B
另一种方法是
public async Task<TestObject> DoSomeWork(string aParam1, object aParam2)
{
TestObject testObj = new TestObject()
..fill state params....
return await Task.Factory.StartNew((state) =>
{
//But now I need to do async/await in here
// is it a good practice to async await lambdas?
// async/await practices say it's ok as long sas it is not becoming async void
// which in our case is not.
await MethodCallAsync(testObj);
....do other work synchronous.....
....continue fill state properties...
await Task.Delay(1000) // just a delay for no reason
...continue synchronous work.....
return state; // Our state and TestObject to examine after completion
}, testObj);
}
我们现在的问题不仅在于我们是否应该异步lambda,比如说你这样做,它将返回一个Task<Task<TestObject>>
,我们绝对不希望这样。
您应该在管道中调用它,很可能是您的GUI类。
private async void SomethingClickedOrTouched(object sender, EventArgs e)
{
await RunThisAsyncToDoYourJob();
}
private async Task RunThisAsyncToDoYourJob()
{
TestObject testObj = await myObject.DoSomeWork("param1", anotherObject);
}
它只是让我有点bug,我真的很想了解异步编程的细节。
那么,A范式是正确的方法吗?只有当代码中的Task lambda完全同步时,才使用B范式?提前谢谢。
谨致问候。
编写async
方法的正确方法是在不需要在捕获的上下文上继续时使用ConfigureAwait(continueOnCapturedContext: false)
。这通常针对所有"库"代码。
这将把我的GUI上下文分割成几个小的调用块,对吧?
是(因为您没有使用ConfigureAwait
)。
或者我不知道从你声明一个方法async的那一刻起,它是否会为里面的所有操作创建一个Task?
是的,async
将创建一个代表async
方法的Task
。然而,存在Task
并不意味着它的代码在后台线程上运行。
它将返回一个
Task<Task<TestObject>>
,我们绝对不希望这样。
我想知道在异步任务中使用Task.Factory.StartNew
的想法是从哪里来的。如果您想在后台线程上运行代码,Task.Run
会更出色。
我的博客上有一个async
的介绍,你可能会觉得有帮助。