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异常时支持递归回调的辅助方法的更多相关文章

  1. 分享我的“艺术品”:公共建筑能耗监测平台的GPRS通讯服务器的开发方法分享

    在这个文章里面我将用一个实际的案例来分享如何来构建一个能够接受3000+个连接的GPRS通讯服务器软件,这个软件被我认为是一个艺术品,实现周期为1.5个月,文章很长,有兴趣的同志慢慢看.在这里,我将分 ...

  2. 分享一个安卓中异步获取网络图片并自适应大小的第三方程序(来自github)

    安卓中获取网络图片,生成缓存 用安卓手机,因为手机流量的限制,所以我们在做应用时,要尽量为用户考虑,尽量少耗点用户的流量,而在应用中网络图片的显示无疑是消耗流量最大的,所以我们可以采取压缩图片或者将图 ...

  3. 分享一个JDK批量异步任务工具CompletionService,超好用

    摘要:当需要批量提交异步任务,推荐CompletionService.CompletionService将线程池Executor和阻塞队列融合,让批量异步任务管理更简单. 本文分享自华为云社区< ...

  4. 【C#】对异步请求处理程序IHttpAsyncHandler的理解和分享一个易用性封装

    在asp.net项目中,添加一个[一般处理程序]来处理请求是很自然的事,这样会得到一个实现自IHttpHandler的类,然后只需在ProcessRequest方法中写上处理逻辑就行了.但是这样的一个 ...

  5. 深入理解Tornado——一个异步web服务器

    本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...

  6. 分享一个c#写的开源分布式消息队列equeue

    分享一个c#写的开源分布式消息队列equeue 前言 equeue消息队列中的专业术语 Topic Queue Producer Consumer Consumer Group Broker 集群消费 ...

  7. 前端分享----JS异步编程+ES6箭头函数

    前端分享----JS异步编程+ES6箭头函数 ##概述Javascript语言的执行环境是"单线程"(single thread).所谓"单线程",就是指一次只 ...

  8. Python:通过一个小案例深入理解IO多路复用

    通过一个小案例深入理解IO多路复用 假如我们现在有这样一个普通的需求,写一个简单的爬虫来爬取校花网的主页 import requests import time start = time.time() ...

  9. [Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手"

    [Unity3D入门]分享一个自制的入门级游戏项目"坦克狙击手" 我在学Unity3D,TankSniper(坦克狙击手)这个项目是用来练手的.游戏玩法来自这里(http://ww ...

随机推荐

  1. HTML5.dcloud.io-stream-app

    dcloud.io提出的Stream App 本文仅仅是关于dcloud.io提出的SteamApp初探,所有内容请参考其官网. 1. Application promotion by scaning ...

  2. NetCDF 入门

    一.概述  NetCDF全称为network Common Data Format,中文译法为“网络通用数据格式”,对程序员来说,它和zip.jpeg.bmp文件格式类似,都是一种文件格式的标准.ne ...

  3. 史上最全的常用iOS的第三方框架

    文章来源:http://blog.csdn.net/sky_2016/article/details/45502921 图像: 1.图片浏览控件MWPhotoBrowser       实现了一个照片 ...

  4. mac上的git completion

    只安装bash-completion,是没有git补全的,因为此时/usr/local/etc/bash-completion.d/下面没有git-XXX.sh 解决方法是brew install g ...

  5. Oracle数据导入导出

    Oracle数据导入导出imp/exp 在oracle安装目录下有EXP.EXE与IMP.EXE这2个文件,他们分别被用来执行数据库的导入导出.所以Oracle数据导入导出imp/exp就相当与ora ...

  6. 一句话的代码,从集合中找出第一个重复字符的方法javascript版。

    有的时候需求是这样的: 找出集合中第一个重复的字符所在的位置,刚才看了园内某自许为算法的代码,感觉非常之啰嗦故写了以下代码! 本人对神马算法之类的完全不懂,但那些伪算法家们也别出来装蒜.一句话:不要欺 ...

  7. esri联邦用户大会 总结

    1 概述 1.1 文档概述 ESRI联邦用户大会已于2月25日到2月27日在美国华盛顿举行,现就其会议中设计到的内容总结如下: 1.2 景观分析 这是第一个demo,演示的是"景观分析&qu ...

  8. C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用)

    C#中的BackgroundWorker控件+Delegate.Invoke (委托同步调用) 简单代码,记录一下.一个BackgroundWorker控件  backgroundWorkerRefr ...

  9. leetcode problem sum

    2. Add Two Numbers You are given two linked lists representing two non-negative numbers. The digits ...

  10. ubuntu 安装JAVA jdk的两种方法:

    ubuntu 安装jdk 的两种方式: 1:通过ppa(源) 方式安装. 2:通过官网下载安装包安装. 这里推荐第1种,因为可以通过 apt-get upgrade 方式方便获得jdk的升级 使用pp ...