我想展示两种关于异步编程的范例并听取你的意见。
:一种。
假设您已在库中创建了类似以下的方法,以便从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上下文切换成小的调用件,对吗?或者我不知道从声明方法异步的那一刻起,它是否会为内部的所有操作创建一个任务?
如果是,那么很好,没问题,我们可以宣布它是异步的并继续我们的生活。
让我们说不,我想采取以下方法,所以我不会打扰GUI,直到我的整个方法调用完成并取结果,所以在我的调用方法中做一些事情。
乙
另一种方法是。
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);
}
它只是让我感到烦恼,我真的想要了解异步编程的细节。
那么,A范式无论如何都是正确的方法,只有当代码中的任务lambda完全同步时才使用B范例? 提前谢谢。
问候。
答案 0 :(得分:6)
编写async
方法的正确方法是在不需要在捕获的上下文上恢复时使用ConfigureAwait(continueOnCapturedContext: false)
。这通常是针对所有“库”代码完成的。
这会将我的GUI上下文切换成小的调用片段,对吗?
是(因为您没有使用ConfigureAwait
)。
或者我不知道从声明方法异步的那一刻开始,它是否会为内部的所有操作创建一个Task?
是的,async
将创建代表Task
方法的async
。但是,存在Task
这一事实并不意味着其代码在后台线程上运行。
它将返回
Task<Task<TestObject>>
,我们绝对不希望这样。
我想知道每个人都想到使用Task.Factory.StartNew
进行异步任务的想法。 Task.Run
is superior if you want to run code on a background thread
我有async
intro on my blog你可能会觉得有帮助。