.NET CoreでASP.NET MVCサイトを作成しています。私はいくつかの一般的な例外処理をカプセル化しようとしています。 Baseクラスでは、私はこのメソッドを持っています。この基本クラスから継承するコントローラからAsync/Awaitタスク操作で例外がキャッチされない
public abstract class BaseController<TController> : Controller where TController : Controller
{
protected IActionResult ExceptionHandledOperation(Func<IActionResult> operation, Func<IActionResult> handleException)
{
try
{
return operation.Invoke();
}
catch (Exception exception)
{
Logger.LogError($"Operation {Request.Path} Exception", exception);
return handleException.Invoke();
}
}
}
、私は同様に、この方法を利用する:
[Route("api/[controller]")]
public class MyController : BaseController<MyController>
{
[HttpGet]
public IActionResult Get()
{
return ExceptionHandledOperation(() => Ok(_someService.GetAsync().Result),
NotFound);
}
}
は_someService.GetAsync()メソッドを想定し、このです:
public class SomeService
{
public async Task<PreconfigurationData> GetAsync()
{
// http request removed for brevity
if (!response.IsSuccessStatusCode)
throw new Exception("SomeService Exception");
}
}
この正常に動作し、基本クラスのメソッドで私の例外をキャッチし、NotFoundの結果を返します。
しかし、私はSomeService.GetAsyncメソッドから.Resultを呼び出すことを避けたかったのです。どこでも、私はそれがデッドロックする可能性があるので、それをしないと言います。このような
public abstract class BaseController<TController> : Controller where TController : Controller
{
protected async Task<IActionResult> ExceptionHandledOperationAsync(Func<IActionResult> operation, Func<IActionResult> handleException)
{
try
{
return await Task.Run(() => operation.Invoke());
}
catch (Exception exception)
{
Logger.LogError($"Operation {Request.Path} Exception", exception);
return await Task.Run(() => handleException.Invoke());
}
}
}
そしてMyController:
は、だから私はこれに私のベースコントローラを修正
[Route("api/[controller]")]
public class MyController : BaseController<MyController>
{
[HttpGet]
public async Task<IActionResult> Get()
{
return await ExceptionHandledOperationAsync(() => Ok(_someService.GetAsync()),
NotFound);
}
}
しかし、私のSomeService.GetAsyncメソッドからスローされた私の例外がキャッチされることはありませんし、私が取得することはありません例外を処理するときに送信する予定のNotFoundレスポンス。
どこでも私はあなたが試しにタスクを待つ必要があると言うと、例外が捕まえられますが、私は決してしません。
私は最終的にこれが解決取得することができた
を解決しました。 Tsengのおかげです。
ASP.NET Coreアプリケーションで「Task.Run」を呼び出さないでください。あなたはそれから一つの利益を得ることはできませんし、あなたのパフォーマンスを低下させるかもしれませんし、あなたはThreadPoolの管理を台無しにするかもしれません。実際に非同期(ファイルIO、ネットワーク、データベースアクセスなど)を実行するawait/asyncのみの操作を使用します。 – Tseng
https://msdn.microsoft.com/en-us/magazine/dn802603.aspx ASP.NETについてASP.NETコアへ – Tseng
@Tseng Task.Runを使用せずにoperation.Invoke()を非同期にする方法を理解できません。 operation.InvokeAsync()はありません。私はTaskFactory.FromAsync(operation.BeginInvoke、operation.EndInvoke、null)を使ってみましたが、例外がスローされました。 – Ristogod