服务器响应 .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 服务的主要功能周围包装了一个锁定语句,并在函数部分中使用了一个布尔值来调用远程服务器。经过多次测试,没有错误。
您似乎遇到了同步问题,只需用锁将迭代列表的代码括起来,您就会没事的。
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 的答案。