我正在编写代码,最后我从另一个异步方法调用异步方法。我想知道这种做法对性能的影响。是否导致为每个async-await使用如此多的线程?
一个例子可以帮助
public async Task<IHttpActionResult> ControllerMethod()
{
:
return await A1();
}
public async Task<R1> A1()
{
:
var result = await A2();
if (result != null)
{
A3()
}
return result;
}
public async Task<R1> A2()
{
:
var result = await A4();
return result;
}
public void A3()
{
:
// call to another async method without await
}
请帮助我理解 - 这是不好的做法?这是重构代码的结果
答案 0 :(得分:1)
成本和性能影响表明,标记为异步的每个方法都会在幕后转移到状态机中;所以必须要处理更多代码和状态机实例。
您可以避免使用重写的状态机,如下所示;如果该语句后面没有代码,则不必等待,只需按照下面的A2方法返回任务即可。
// PackageControllerTest.php
namespace Tests\Feature;
use Tests\TestCase;
use App\Contracts\PackageInterface;
use App\Http\Controllers\PackageController;
use Illuminate\Database\Eloquent\Collection;
class PackageControllerTest extends TestCase
{
protected $mock;
protected $target;
public function setUp()
{
parent::setUp();
parent::initDatabase();
$this->mock = $this->initMock(PackageInterface::class);
$this->target = $this->app->make(PackageController::class);
}
public function testIndex()
{
$expected = new Collection([
['name' => 'Name 1', 'html_url' => 'HTML URL 1'],
['name' => 'Name 2', 'html_url' => 'HTML URL 2'],
['name' => 'Name 3', 'html_url' => 'HTML URL 3'],
]);
$this->mock
->shouldReceive('getAllPackages')
->once()
->andReturn($expected);
$actual = $this->target->index()->packages;
$this->assertEquals($expected, $actual);
}
public function testUpdate()
{
//
}
public function tearDown()
{
parent::resetDatabase();
$this->mock = null;
$this->target = null;
}
}
答案 1 :(得分:0)
这完全不是一个坏习惯。如果您正在分解的小方法做了一些真正需要异步操作的工作,则情况正好相反。假设在方法 A4()中,您正在从文件中读取数据(非CPU绑定操作,不需要来自ASP .NET线程池的任何线程)。如果您在此操作中不使用异步,则在从文件中读取数据时,您的线程将无法执行任何操作。
相反,如果你使用异步,线程将返回到线程池,并且线程池将能够用新释放的线程提供更多请求。