这是添加在C#中的同步/异步任务重试/回​​滚机制的最佳方式? [英] Which is the best way to add a retry/rollback mechanism for sync/async tasks in C#?

查看:1006
本文介绍了这是添加在C#中的同步/异步任务重试/回​​滚机制的最佳方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试想一个WebForms的应用程序,其中有()命名CreateAll一个主要方法。我可以一步描述方法的任务步骤的过程如下:

1)存储到数据库中(更新/创建分贝项目3-4次)

2)启动一个新线程

3)结果1 =调用SOAP服务,并通过它检查的地位和X分钟。它继续后(现在的地位是确定,它不意味着失败)超时阈值

4)存储到数据库中(更新/创建分贝项目3-4次)

5)RESULT2 =调用一个SOAP服务(在发射后不管的方式)

6)更新的配置文件(即从RESULT1实际采取)

7)通过使用回调要求它的前部检查每x秒的结果2的状态和UI显示bar.If过程完成进度(100%),这意味着成功

我考虑到所有的人都可以通过type.Basically分组任务的几种类型的操作是:


  • 类型1:DB事务

  • 类型2:服务通信/事务

  • 类型3:配置文件I / O事务

我想补充回滚/重试机制,以现有的执行情况,并使用一个任务为导向的架构和重构现有的传统code。

我发现,类似的纪念品设计模式命令模式在C#中可以帮助这个purpose.I还发现在MSDN的重试模式说明有趣。我不知道真的,我希望有人来领我到最安全,最好的决定...

您可以给我建议这种情况下保留现有的执行和流,但最好的方式在一般的,抽象的重试/回滚/任务列表实现包装呢?

最终实现必须能够每一种情况下重试(无论任务或一般故障,如超时等整个通用createAll流程),也将有一个回滚决定列表,应用程序必须能够回滚所有任务这是完成了。

我要一些例子来说明如何打破这一再加code。


伪code可能会有所帮助:

 类的东西
{
    静态结果CreateAll(object1 OBJ1,Object2的OBJ2 ...)
    {
        //保存到数据库OBJ1
        // ...
        //更新数据库OBJ1
        //
        //新线程
       //开始一个新线程OBJ1,OBJ2 ... CreateAll
       // ...
     }    无效CreateAllAsync()
    {
        //类型1保存到数据库OBJ1
        // ...
        //类型1更新数据库OBJ2        // 2型呼叫Web服务上的服务(而不是异步)创建OBJ1        而(州= NULL&放大器;!&安培;现在<次)
        {
            如果(状态==OK)
            打破;
            其他
            //等待X秒
        }        //检查状况继续或一般故障
        //类型1更新数据库OBJ2和OBJ1        //类型2调用Web服务创建OBJ2上的服务(火灾和忘记)        // 3类更新配置文件
        //类型1更新数据库OBJ2和OBJ1
        // ..    返回;
}//然后,UI需要负责检查结果2的状态


解决方案

看看使用波利重试这似乎与你的伪code调整好方案。在这个答案到底是从文档的样本。你可以做各种重试的情况,重试,等待等。例如,你可以重试一个完整交易的次数,或者重试一组幂等操作的次数,然后写补偿逻辑,如果/当重试政策终于失败。

纪念图案则多为撤消,重做逻辑你会发现在一个文字处理器(按Ctrl-Z和Ctrl-U)。

其他有用的模式来看待是一个简单的队列,持久队列,甚至是服务总线,给你最终一致性,而不必让用户等待一切都成功完成。

  //重试三次,呼吁每个重试动作
//与当前异常和重试次数
政策
    .Handle< D​​ivideByZeroException>()
    .Retry(3,(例外,RetryCount重)=>
    {
        // 做一点事
    });

根据您的伪code可以看作为样本如下:

 静态布尔CreateAll(object1 OBJ1,Object2的OBJ2)
{
     //政策重试3次,等待重试间隔5秒钟。
     VAR政策=
         政策
              .Handle<&的SQLException GT;()
              .WaitAndRetry(3,计数=>
              {
                 返回TimeSpan.FromSeconds(5);
              });       policy.Execute(()=> UpdateDatabase1(OBJ1));
       policy.Execute(()=> UpdateDatabase2(obj2的));
  }

Imagine of a WebForms application where there is a main method named CreateAll(). I can describe the process of the method tasks step by step as follows:

1) Stores to database (Update/Create Db items 3-4 times)

2) Starts a new thread

3) Result1 = Calls a soap service, and by using a timeout threshold it checks the status and after x minutes.The it continues (status now is OK and it isn't means failure)

4) Stores to database (Update/Create Db items 3-4 times)

5) result2 = Calls a soap service (In a fire and forget way)

6) Updates a configuration file (that is taken actually from result1)

7) By using callback requests it checks every x secs at front part the state of the result2 and the UI shows a progress bar.If the process is finished (100%) it means success

I am considering that all of them are tasks that can be grouped by their type.Basically the several types of actions are :

  • Type1: DB transaction
  • Type2: Service communication/transaction
  • Type3: Config file I/O transactions

I want to add a rollback/retry mechanism to the existing implementation and to use a task oriented architecture and refactor existing legacy code.

I found that something like Memento Design Pattern OR Command Pattern in C# could help for this purpose.I also found the msdn Retry Pattern description interesting. I don't realy know and I want someone to lead me to the safest and best decision...

Can you suggest me the best way for this case to keep the existing implementation and the flow but wrapping it in a general and abstract retry/rollback/tasklist implementation ?

The final implementation must be able to retry in every case (whatever task or general failure such as timeout etc throughout the general createAll process) and also there would be a rollback decision list where the app must be able to rollback all the tasks that was accomplished.

I want some examples how to break this coupled code.


PseudoCode that might be helpful:

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

解决方案

Look at using Polly for retry scenarios which seems to align well with your Pseudo code. At the end of this answer is a sample from the documentation. You can do all sorts of retry scenarios, retry and waits etc. For example, you could retry a complete transaction a number of times, or alternatively retry a set of idempotent actions a number of times and then write compensation logic if/when the retry policy finally fails.

A memento patterns is more for undo-redo logic that you would find in a word processor (Ctrl-Z and Ctrl-U).

Other helpful patterns to look at is a simple queue, a persistent queue or even a service bus to give you eventual consistency without having to have the user wait for everything to complete successfully.

// 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 
    });

A sample based on your Pseudo-Code may look as follows:

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#中的同步/异步任务重试/回​​滚机制的最佳方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆