分享一个异步任务在遇到IO异常时支持递归回调的辅助方法
public void TryAsyncActionRecursively<TAsyncResult>(
string asyncActionName,
Func<Task<TAsyncResult>> asyncAction,
Action<int> mainAction,
Action<TAsyncResult> successAction,
Func<string> getContextInfoFunc,
Action<Exception> failedAction,
int retryTimes) where TAsyncResult : AsyncOperationResult
{
var retryAction = new Action<int>(currentRetryTimes =>
{
if (currentRetryTimes >= _immediatelyRetryTimes)
{
Task.Factory.StartDelayedTask(_retryIntervalForIOException, () => mainAction(currentRetryTimes + ));
}
else
{
mainAction(currentRetryTimes + );
}
});
var executeFailedAction = new Action<Exception>(ex =>
{
try
{
if (failedAction != null)
{
failedAction(ex);
}
}
catch (Exception unknownEx)
{
_logger.Error(string.Format("Failed to execute the failedCallbackAction of asyncAction:{0}, contextInfo:{1}",
asyncActionName, getContextInfoFunc()), unknownEx);
}
});
var processTaskException = new Action<Exception, int>((ex, currentRetryTimes) =>
{
if (ex is IOException)
{
_logger.Error(string.Format("Async task '{0}' has io exception, contextInfo:{1}, current retryTimes:{2}",
asyncActionName, getContextInfoFunc(), currentRetryTimes), ex);
retryAction(retryTimes);
}
else
{
_logger.Error(string.Format("Async task '{0}' has unknown exception, contextInfo:{1}, current retryTimes:{2}",
asyncActionName, getContextInfoFunc(), currentRetryTimes), ex);
executeFailedAction(ex);
}
});
var completeAction = new Action<Task<TAsyncResult>>(t =>
{
if (t.Exception != null)
{
processTaskException(t.Exception.InnerException, retryTimes);
return;
}
if (t.IsCanceled)
{
_logger.ErrorFormat("Async task '{0}' was cancelled, contextInfo:{1}, current retryTimes:{2}",
asyncActionName, getContextInfoFunc(), retryTimes);
retryAction(retryTimes);
return;
}
var result = t.Result;
if (result.Status == AsyncOperationResultStatus.IOException)
{
_logger.ErrorFormat("Async task '{0}' has io exception, contextInfo:{1}, current retryTimes:{2}, errorMsg:{3}",
asyncActionName, getContextInfoFunc(), retryTimes, result.ErrorMessage);
retryAction(retryTimes);
return;
}
if (successAction != null)
{
successAction(result);
}
}); try
{
asyncAction().ContinueWith(completeAction);
}
catch (IOException ex)
{
_logger.Error(string.Format("Execute async action '{0}' failed, contextInfo:{1}, current retryTimes:{2}",
asyncActionName, getContextInfoFunc(), retryTimes), ex);
retryAction(retryTimes);
}
catch (Exception ex)
{
_logger.Error(string.Format("Execute async action '{0}' failed, contextInfo:{1}, current retryTimes:{2}",
asyncActionName, getContextInfoFunc(), retryTimes), ex);
executeFailedAction(ex);
}
}
该函数的功能是:执行一个异步任务(返回Task的方法),如果执行出现IO异常,则重试当前主函数(mainAction);用户的mainAction中会再次调用TryAsyncActionRecursively方法。从而实现当遇到IO异常时,能做到不断重试。另外,重试只立即重试指定的次数,超过指定次数,则不立即重试,而是暂停一定间隔后再次执行。该函数还提供当acyncAction执行成功或失败后的回调函数,以及允许传入当前上下文的一些说明信息,以便记录有意义的错误日志信息。
下面是使用示例:
private void PublishEventAsync(ProcessingCommand processingCommand, EventStream eventStream, int retryTimes)
{
TryAsyncActionRecursively<AsyncOperationResult>("PublishEventAsync",
() => _eventPublisher.PublishAsync(eventStream),
currentRetryTimes => PublishEventAsync(processingCommand, eventStream, currentRetryTimes),
result =>
{
_logger.DebugFormat("Publish events success, {0}", eventStream);
processingCommand.Complete(new CommandResult(CommandStatus.Success, processingCommand.Command.Id));
},
() => string.Format("[eventStream:{0}]", eventStream),
ex => processingCommand.Complete(new CommandResult(CommandStatus.Failed, processingCommand.Command.Id)),
retryTimes);
}
PublishEventAsync(processingCommand, eventStream, );
分享一个异步任务在遇到IO异常时支持递归回调的辅助方法的更多相关文章
- 分享我的“艺术品”:公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享
在这个文章里面我将用一个实际的案例来分享如何来构建一个能够接受3000+个连接的GPRS通讯服务器软件,这个软件被我认为是一个艺术品,实现周期为1.5个月,文章很长,有兴趣的同志慢慢看.在这里,我将分 ...
- 分享一个安卓中异步获取网络图片并自适应大小的第三方程序(来自github)
安卓中获取网络图片,生成缓存 用安卓手机,因为手机流量的限制,所以我们在做应用时,要尽量为用户考虑,尽量少耗点用户的流量,而在应用中网络图片的显示无疑是消耗流量最大的,所以我们可以采取压缩图片或者将图 ...
- 分享一个JDK批量异步任务工具CompletionService,超好用
摘要:当需要批量提交异步任务,推荐CompletionService.CompletionService将线程池Executor和阻塞队列融合,让批量异步任务管理更简单. 本文分享自华为云社区< ...
- 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装
在asp.net项目中,添加一个[一般处理程序]来处理请求是很自然的事,这样会得到一个实现自IHttpHandler的类,然后只需在ProcessRequest方法中写上处理逻辑就行了.但是这样的一个 ...
- 深入理解Tornado——一个异步web服务器
本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...
- 分享一个c#写的开源分布式消息队列equeue
分享一个c#写的开源分布式消息队列equeue 前言 equeue消息队列中的专业术语 Topic Queue Producer Consumer Consumer Group Broker 集群消费 ...
- 前端分享----JS异步编程+ES6箭头函数
前端分享----JS异步编程+ES6箭头函数 ##概述Javascript语言的执行环境是"单线程"(single thread).所谓"单线程",就是指一次只 ...
- Python:通过一个小案例深入理解IO多路复用
通过一个小案例深入理解IO多路复用 假如我们现在有这样一个普通的需求,写一个简单的爬虫来爬取校花网的主页 import requests import time start = time.time() ...
- [Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手"
[Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手" 我在学Unity3D,TankSniper(坦克狙击手)这个项目是用来练手的.游戏玩法来自这里(http://ww ...
随机推荐
- PTGM and APTM
1. 性能测试过程模型(PTGM) PTGM模型包括以下几个步骤: 测试前期的准备 测试工具的引入 测试计划 测试设计与开发 测试执行与管理 测试分析 测试前期准备:主要任务为保证系统稳定和建立合适的 ...
- 调整Win7中TCP/IP半开连接数限制
调整Win7中TCP/IP半开连接数限制 相信大家都有过这样的经历,普通的ADSL宽带下,打开下载工具下载资源时,再想浏览网页就会变得非常困难了,Windows7中也未能幸免. 究其原因 ...
- php namespace用法
其实纠结了很久要不要使用这个东西,但是看看了最新的框架laravel,cakephp等等的新版本都使用上了,所以还是随大流顺便学习下. namespace和c++里面的概念差不多,只是用法有点差别. ...
- pip 安装 lxml 出错
用pip安装 lxml 老是出错,在公司安装了 wheel,从 http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml 下载了lxml的whl包,pip ins ...
- python json模块
import json dic = {"name":"liao","age":18} data = json.dumps(dic) #转化为 ...
- NLS_LANG
NLS_LANG是一个环境变量,用于定义语言,地域以及字符集属性.对于非英语的字符集,NLS_LANG的设置就非常重要. NLS:‘National Language Support (NLS)’ 当 ...
- 20145202、20145225、20145234 《信息安全系统设计基础》实验五 简单嵌入式WEB 服务器实验
实验内容 1.配置环境 2.使用vi 编辑器阅读理解源码 2.编译应用程序 运行 make 产生可执行文件httpd 3.下载调试 使用 NFS 服务方式将HTTPD 下载到开发板上,并拷贝测试用的网 ...
- 原生JS中apply()方法的一个值得注意的用法
今天在学习vue.js的render时,遇到需要重复构造多个同类型对象的问题,在这里发现原生JS中apply()方法的一个特殊的用法: var ary = Array.apply(null, { &q ...
- [ MySql学习心得 ] --One
一.安装MySql 1.解压版安装 下载地址: http://dev.mysql.com/downloads/mysql/ 安装及配置教程:http://jingyan.baidu.com/artic ...
- .net 常用的命名空间和类
一.基础命名空间 l System.Collections 包含了一些与集合相关的类型,比如列表,队列,位数组,哈希表和字典等. l System.IO 包含了一些数据流类型并提供了文件和目录同步 ...