想象一个 WebForms 应用程序,其中有一个名为 CreateAll() 的主要方法。我可以逐步描述方法任务的过程如下:
1) 存储到数据库(更新/创建 Db 项目 3-4 次)
2) 开始一个新线程
3) Result1 = 调用 soap 服务,并通过使用超时阈值检查状态并在 x 分钟后继续。它继续(现在状态正常,并不意味着失败)
4) 存储到数据库(更新/创建 Db 项目 3-4 次)
5) result2 = 调用 soap 服务(以即刻即弃的方式)
6) 更新配置文件(实际取自 result1)
7) 通过使用回调请求,它会在前面每隔 x 秒检查一次结果 2 的状态,并且 UI 会显示一个进度条。如果过程完成 (100%),则表示成功
我正在考虑所有这些都是可以按类型分组的任务。基本上,几种类型的操作是:
- 类型 1:数据库事务
- Type2:服务沟通/交易
- 类型 3:配置文件 I/O 事务
我想为现有的实现添加回滚/重试机制,并使用面向任务的架构并重构现有的遗留代码。
我发现 C# 中的 Memento Design Pattern 或 Command Pattern 之类的东西可以帮助实现这一目的。我还发现了 msdn Retry Pattern描述很有趣。我真的不知道,我希望有人能引导我做出最安全和最好的决定...
对于这种情况,您能否建议我保留现有实现和流程但将其包装在通用和抽象的重试/回滚/任务列表实现中的最佳方法?
最终实现必须能够在每种情况下重试(无论是什么任务或一般故障,例如整个 createAll 过程中的超时等),并且还有一个回滚决策列表,应用程序必须能够回滚所有任务完成了。
我想要一些如何打破这种耦合代码的例子。
可能有用的伪代码:
class something
{
static result CreateAll(object1 obj1, object2 obj2 ...)
{
//Save to database obj1
//...
//Update to database obj1
//
//NEW THREAD
//Start a new thread with obj1, obj2 ...CreateAll
//...
}
void CreateAllAsync()
{
//Type1 Save to database obj1
//...
//Type1 Update to database obj2
//Type2 Call Web Service to create obj1 on the service (not async)
while (state != null && now < times)
{
if (status == "OK")
break;
else
//Wait for X seconds
}
//Check status continue or general failure
//Type1 Update to database obj2 and obj1
//Type2 Call Web Service to create obj2 on the service (fire and forget)
//Type3 Update Configuration File
//Type1 Update to database obj2 and obj1
//..
return;
}
//Then the UI takes the responsibility to check the status of result2
最佳答案
看看使用Polly对于似乎与您的伪代码一致的重试场景。此答案的末尾是文档中的示例。您可以执行各种重试场景,重试和等待等。例如,您可以多次重试一个完整的事务,或者多次重试一组幂等操作,然后在重试时编写补偿逻辑政策最终失败。
备忘录模式更适用于文字处理器(Ctrl-Z 和 Ctrl-Y)中的撤消-重做逻辑。
要查看的其他有用模式是简单队列、持久队列甚至服务总线,它们可为您提供最终一致性,而无需让用户等待一切成功完成。
// Retry three times, calling an action on each retry
// with the current exception and retry count
Policy
.Handle<DivideByZeroException>()
.Retry(3, (exception, retryCount) =>
{
// do something
});
基于您的伪代码的示例可能如下所示:
static bool CreateAll(object1 obj1, object2 obj2)
{
// Policy to retry 3 times, waiting 5 seconds between retries.
var policy =
Policy
.Handle<SqlException>()
.WaitAndRetry(3, count =>
{
return TimeSpan.FromSeconds(5);
});
policy.Execute(() => UpdateDatabase1(obj1));
policy.Execute(() => UpdateDatabase2(obj2));
}
关于c# - 在 C# 中为同步/异步任务添加重试/回滚机制的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37393828/