1

我想展示两个关于异步编程的范例并听取您的意见。

一个。

假设您在库中创建了一个类似以下的方法,以便从您的 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,直到我的整个方法调用完成并获取结果,所以在我的调用方法中做一些事情。

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,比如说你这样做,它会返回 a 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 范式是否是正确的方法,并且仅当代码中的 Task lambda 完全同步时才使用 B 范式?先感谢您。

问候。

4

1 回答 1

6

编写方法的正确async方法是在不需要恢复捕获的上下文ConfigureAwait(continueOnCapturedContext: false)时使用。这通常适用于所有“库”代码。

这会将我的 GUI 上下文分割成小的调用片段,对吗?

是的(因为您没有使用ConfigureAwait)。

或者我不知道从你声明一个异步方法的那一刻起,它是否会为里面的所有操作创建一个任务?

是的,async将创建一个Task表示该方法的async方法。但是,有 a 的事实Task并不意味着它的代码在后台线程上运行。

它会返回 a Task<Task<TestObject>>,我们绝对不希望这样。

我想知道每个人都从哪里得到使用Task.Factory.StartNew异步任务的想法。Task.Run如果你想在后台线程上运行代码,那就更好了


我的博客上有一个async介绍,您可能会觉得有帮助。

于 2013-08-25T02:13:17.793 回答