0

我有一个创建多个线程来发出 HTTP 请求的应用程序。我面临的问题是,如果请求失败,线程将被中止。我需要一些关于如何在新线程或现有线程中重新发出相同请求的想法。我正在使用 BlockingCollection 添加和取消从 HTTP 请求中提取的项目。这并不重要,但有助于理解我在做什么。请记住,HTTP 请求可能失败的原因有很多,因此我不会发布请求的实际代码。我正在使用 HTTPClient 类来发出请求。

示例代码:

private void StartIntegration()
        {
            var queuCount = 0;

            var totalToSend = GetTotalToSendFromDb();

            for (int i = 0; i < 10; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (queuCount != totalToSend)
                    {
                        //Get 500 items form the database to pass into the request                            
                        var items = GetRequestsFromDB(500);
                        if (items != null && items.Count > 0)
                        {
                            queuCount += items.Count;
                            SendRequest(mailing);
                        }


                    }
                });
            }


            for (int i = 0; i < 10; i++)
            {
                Task.Factory.StartNew(() => ConsumeResults());
            }

            while (_someGlobalVariable)
            {
                //Loop until the variable is false.

            }


        }
4

1 回答 1

0

经过一番挖掘后,请求存在一些问题以及实际返回的内容。最初,我只是捕捉到一个通用异常。在更改它以捕获 AggregateException 之后,我能够找出请求错误的原因,反过来,我能够再次调用该方法。我在该方法中添加了一个变量,因此它只会在放弃之前重试 X 次。

另一个问题是我如何从数据库中取回数据。存储过程如下所示:

Create PROCEDURE [dbo].[GetTopListEmailItems](

@topCount   INT) 
AS 
  BEGIN 
      BEGIN 
          -- Identify the next N emails to be batched. UPDLOCK is to prevent another thread batching same emails
          SELECT TOP (@topCount) id 
          INTO   #tmpbatch 
          FROM  (SELECT  
                        Id, 
                        Md5Hash,
                                                EmailAddress,
                                                IsProcessed
                 FROM   ListEmailItems WITH (updlock,HOLDLOCK)) tmp 
          WHERE IsProcessed  = 0

          -- Stamp emails as sent. Assumed that PROC is called under a UOW. The batch IS the UOW 
          UPDATE e 
          SET    e.IsProcessed = 1 
          FROM   dbo.ListEmailItems e 
                 INNER JOIN #tmpbatch t 
                         ON e.id = t.id 

          -- Return the batch of emails to caller 
          SELECT e.* 
          FROM   dbo.ListEmailItems e 
                 INNER JOIN #tmpbatch t 
                         ON e.id = t.id 
      END 
  END  

此过程应该只获取 TopX记录并阻塞线程,因此不会多次提取相同的记录。问题出在 C# 代码上。在事务中包装 DB 调用后,它不再多次提取相同的记录。

private List<ListEmailItem> GetRequests(int topCount,bool reset = false)
        {
            List<ListEmailItem> items;
            using (var tran = new TransactionScope(
                // a new transaction will always be created
                TransactionScopeOption.RequiresNew,
                // we will allow volatile data to be read during transaction
                new TransactionOptions()
                {
                    IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
                }
                ))
            {
                using (var context = new IntegrationContext())
                {
                    items = context.Database.SqlQuery<ListEmailItem>("Exec GetTopListEmailItems @topCount",
                        new SqlParameter("topCount", topCount)).Select(s => new ListEmailItem()
                        {
                            Id = s.Id,
                            Md5Hash = s.Md5Hash,
                            EmailAddress = s.EmailAddress,

                        }).ToList();


                }

                tran.Complete();
            }

            return items;
        }
于 2013-10-29T11:44:12.863 回答