我正在用。NET核心编写一个ASP.NET MVC站点。我试图封装一些常见的异常处理。在基类中,我有这个方法。
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());
}
}
}
[Route("api/[controller]")]
public class MyController : BaseController<MyController>
{
[HttpGet]
public async Task<IActionResult> Get()
{
return await ExceptionHandledOperationAsync(() => Ok(_someService.GetAsync()),
NotFound);
}
}
但是,从SomeService.getAsync方法引发的异常从未被捕获,而且在处理异常时,我从未获得打算发送的NotFound响应。
我读到的每一个地方都说你只需要在尝试中等待任务,然后任何异常都会被发现,但我的从来没有。
已解决
您的代码中有一个逻辑错误。您调用return await task.run(()=>handleexception.invoke());
但是在函数委托中,您运行异步代码而不等待它(这里:await ExceptionHandledOperationAsync(()=>Ok(_someservice.getasync()),NotFound)
。
因此,在try/catch块中,在异步调用完成之前,该方法将被执行并立即返回。
正如我的建议中所指出的,函数委托也需要是可等待的,请阅读:returnstask
。
public abstract class BaseController<TController> : Controller where TController : Controller
{
protected async Task<IActionResult> ExceptionHandledOperationAsync<T>(
Func<Task<T>> operation,
Func<object, IActionResult> successHandler,
Func<IActionResult> exceptionHandler
)
{
try
{
return successHandler.Invoke(await operation.Invoke());
}
catch (Exception exception)
{
//Logger.LogError($"Operation {Request.Path} Exception", exception);
return exceptionHandler.Invoke();
}
}
}
[Route("api/[controller]")]
public class MyController : BaseController<MyController>
{
[HttpGet]
public async Task<IActionResult> Get()
{
return await ExceptionHandledOperationAsync(() => _someService.GetAsync(), Ok, NotFound);
}
}
您还需要将successshandler
(将结果传递给OK
)移动到该方法中,如上图所示。但它真的是丑陋的代码。因此,SomeService
应该自己处理服务故障,并在未找到任何值时返回null
。
异常时返回notfound()
似乎非常奇怪,因为它表明记录不存在,但可能由于网络连接或数据序列化而失败。
我正在与async Wait try catch块斗争几天。 这个异步函数中的try-catch是否正确? 这就是我创建自定义错误类并全局导出的方式。 要求: 故意换了工作。我想找份工作。国际直拨电话 这样我就能抓住错误。如果有错误,则抛出新创建的自定义错误类。但抛出队列错误将导致日志记录 同样,即使不需要捕捉那个里的错误,因为try块在工作,若我抛出QueueError,我只想捕捉最后一个cat
问题内容: 我想同时下载一些文件,例如100个文件。因此,我决定将下载线程添加到调度队列中,GCD会调整同时运行多少个线程。 这里的问题是:中的块将立即完成,因为它将在另一个线程上运行。因此,如果长度为100,它将立即创建100个线程。 如何配置块以等待下载任务完成?我不想使用,因为它只允许同时运行一个下载任务。 问题答案: 要扩展Abhinav的答案,您应该: 使用创建一个组。 在开始每个下载任
问题内容: 我不确定如何处理这种情况,因为我是iOS开发和Swift的新手。我正在像这样执行数据获取: 我的loadShows()函数解析从加载到UIWebView的网站中获取的大量数据。问题是我在loadShows函数中有一个等待10秒钟左右的计时器。这允许页面中的javascript在开始解析数据之前完全加载。我的问题是完成处理程序在我的loadShows()之前完成。 我想做的是为“ isC
问题内容: 我正在研究节点7异步/等待功能,并不断跨这样的代码绊脚 这似乎是使用异步/等待解决/拒绝或返回/抛出的唯一可能性,但是,v8不会在try / catch块中优化代码吗? 有其他选择吗? 问题答案: 备择方案 替代方法: 显式地使用诺言将是这样的: 或类似的东西,使用延续传递样式: 原始例子 您的原始代码所做的是暂停执行并等待由其返回的诺言解决。然后,它继续执行,并将返回的值写入,如果承
我试图在react/electron项目中使用async/await,但它不起作用。我想要的是获取docker容器状态列表。但是安慰。日志(列表)返回未定义的。 有人能帮我吗?:)
我只想确保我很好地理解异步await和task.run或task.whenall之间的区别 所以异步等待就是处理异步方法。它意味着隐含着一个处理顺序。 我在不阻塞主线程的情况下运行了一个很长的处理,并等待结果继续。 对于task.run和task.when,这里有一个多线程的新概念。这意味着我可以在一个新线程上启动一个长进程,它不会等待完成来继续代码。代码在新线程上。在这个线程上,我可以等待方法。