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. 前端工作面试问题--摘取自github

    前端工作面试问题 本文包含了一些用于考查候选者的前端面试问题.不建议对单个候选者问及每个问题 (那需要好几个小时).只要从列表里挑选一些,就能帮助你考查候选者是否具备所需要的技能. 备注: 这些问题中 ...

  2. keepalived高可用

    keepalived介绍 Keepalived是一个基于vrrp协议的高可用方案,vrrp协议的软件实现,原生设计的目的为了高可用ipvs服务. 1. vrrp协议 VRRP是一种容错协议,它通过把几 ...

  3. JWPlayer第一个例子

    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding= ...

  4. jQuery事件笔记

    bind(eventType[,data],hanlder):eventType表示要创建的处理器指定事件类型的名称.可以使用空格分隔的列表指定多个事件类型.data(对象)调用者提供的数据,用来附加 ...

  5. shell <<EOF

    1.考虑下面的需求,在主shell执行命令,进入其他的命令,后面的输入,想作为命令的输入,而不是主shell的输入,怎么办? 2.使用<<EOF,告诉主shell,后续的输入,是其他命令或 ...

  6. QQ屠龙转世-挖矿

    ※◆☆★☆◆※欢迎使用QQ屠龙转世辅助,如有疑问请联系作者QQ:82850696*2*测试版已停用*1*2014-8-27 14:05:59*哈密*E2873D0137C6D04F42E088AA46 ...

  7. make: Nothing to be done for `first'

    在qt目录下make后出现以下错误: make: Nothing to be done for `first' 解决:将你当前目录下的,删除你程序主要的 *.cpp 和 *.h文件以外的所有文件. 接 ...

  8. saas简介

    SaaS是Software-as-a-Service(软件即服务)的简称,随着互联网技术的发展和应用软件的成熟, 在21世纪开始兴起的一种完全创新的软件应用模式.它与“on-demand softwa ...

  9. socket网络间通信初识

    NSOperation: 1. 指定同一时间最大执行的操作数 queue.max…… 2. 设定队列中的任务时间的依赖关系 task1 依赖于 task2: task2 —> task1 3. ...

  10. 前台js与后台方法互调

    一:后台调用前台js的方法 ClientScript.RegisterStartupScript(ClientScript.GetType(), "myscript", " ...