服务器响应 .net 上的重复条目

本文关键字:响应 net 服务器 | 更新日期: 2023-09-27 18:05:50

>场景

一个窗口服务每两分钟轮询一次 url 以检索某些数据。

如果自上次调用以来添加了任何数据,则会检索并存储数据,否则循环将继续。

问题

有时,请求需要两分钟以上才能返回响应。

发生这种情况时,仍然发出下一个请求并找到新数据,因为上一个请求尚未返回响应

这会导致在存储数据时出现重复条目。

我尝试过什么

我试图通过使用布尔值来处理这个问题,如下所示:

Boolean InProgress = true;
foreach (var item in Lists)
{ 
''Make a request and return new data (if any)
InProgress = false;
if (InProgress = false)
  {
  ''Store new data
  }
}

这并不能解决问题。我相信我在错误的地方使用了布尔值,但我不确定它应该在哪里。

这是发出请求并存储数据的循环

void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            Data getCredentials = new Data();
            DataTable credentials = getCredentials.loadCredentials();
            Boolean InProgress = true;
            for (int i = 0; i < credentials.Rows.Count; i++)
            {
                if (credentials != null)
                {
                    var PBranchID = (int)credentials.Rows[i]["PortalBranchID"];
                    var negRef = (int)credentials.Rows[i]["NegotiatorRef"];
                    var Username = credentials.Rows[i]["Username"].ToString();
                    var Password = credentials.Rows[i]["Password"].ToString();
                    var Domain = credentials.Rows[i]["Domain"].ToString();
                    var FooCompanyBaseUrl = "https://" + Domain + ".FooCompany.com/";
                    Data getCalls = new Data();
                    DataTable calls = getCalls.loadCalls(PBranchID);
                    //If it's not the first call
                    if (calls != null && calls.Rows.Count > 0)
                    {
                        //Makes a call
                        DateTime CreatedSince = DateTime.SpecifyKind((DateTime)calls.Rows[0]["LastSuccessOn"], DateTimeKind.Local);
                        string IssueListUrl = FooCompany.WebApi.V2.URLs.Issues(BaseUrl, null, CreatedSince.ToUniversalTime(), null);
                        FooCompany.WebApi.V2.DTO.PrevNextPagedList resultIssueList;
                        resultIssueList = FooCompany.WebApi.Client.Helper.Utils.Getter<Foocompany.WebApi.V2.DTO.PrevNextPagedList>(IssueListUrl, Username, Password);
                        InProgress = false;
                        if (InProgress == false)
                        {
                            if (resultIssueList.Items.Count > 0)
                            {
                                //If call returns new issues, save call
                                Data saveCalls = new Data();
                                saveCalls.saveCalls(PBranchID);
                                foreach (var item in resultIssueList.Items)
                                {
                                    var Issue = FooCompany.WebApi.Client.Helper.Utils.Getter<FooCompany.WebApi.V2.DTO.Issue>(item, Username, Password);
                                    string TenantSurname = Issue.Surname;
                                    string TenantEmail = Issue.EmailAddress;
                                    Data tenants = new Data();
                                    int tenantPropRef = Convert.ToInt32(tenants.loadTenantPropRef(PBranchID, TenantSurname, TenantEmail));
                                    Data Properties = new Data();
                                    DataTable propAddress = Properties.loadPropAddress(PBranchID, tenantPropRef);
                                    var Address1 = propAddress.Rows[0]["Address1"];
                                    var Address2 = propAddress.Rows[0]["Address2"];
                                    var AddressFolder = Address1 + "," + Address2;
                                    if (!Directory.Exists("path"))
                                    {
                                        Directory.CreateDirectory("path");
                                    }
                                    string ReportPDFDestination = "path";
                                    if (File.Exists(ReportPDFDestination))
                                    {
                                        File.Delete(ReportPDFDestination);
                                    }
                                    FooCompany.WebApi.Client.Helper.Utils.DownloadFileAuthenticated(FooCompany.WebApi.V2.URLs.IssueReport(BaseUrl, Issue.Id), Username, Password, ReportPDFDestination);

                                    //Store data 
                                }
                                IssueListUrl = resultIssueList.NextURL;
                            }
                        }
                }
                else
                {
                    continue;
                }
            }
        }

        catch (Exception ex)
        {
            //write to log
        }
    }

问题

我相信有比布尔值更好的方法。

谁能建议一种不同的方法来正确处理这个问题?谢谢。

溶液

我最终使用了托马斯和梅森建议的组合。我在 Windows 服务的主要功能周围包装了一个锁定语句,并在函数部分中使用了一个布尔值来调用远程服务器。经过多次测试,没有错误。

服务器响应 .net 上的重复条目

您似乎遇到了同步问题,只需用锁将迭代列表的代码括起来,您就会没事的。

public class MyClass{
private readonly object internalLock= new object();
private bool AlreadyRunning { get;  set; }
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    if(AlreadyRunning){
        return;
    }
    try{
        lock(internalLock){     
            Thread.MemoryBarrier();
            if(AlreadyRunning){
                return;
            }
            AlreadyRunning = true;
            ...Do all the things...
        }
    }
    catch(Exception e){
        ..Exception handling
    }
    finally
    {
        AlreadyRunning = false;
    }
}
bool InProgress=false;
void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
    if(!InProgress)
        {
        InProgress=true;
        //retrieve data
        InProgress=false;
        }
    }

需要在事件处理程序外部声明 InProgress 变量。输入方法时,请检查它是否已运行。如果是,那么我们什么都不做。如果它没有运行,那么我们说它正在运行,检索我们的数据,然后重置我们的标志,说我们已经完成了运行。

您可能需要为线程安全添加适当的锁,类似于 Thomas 的答案。