如何使用foreach向服务器发送请求,当我收到响应时,foreach等待返回的信息进行处理,然后再继续下一个请求。
我的问题:在foreach中,我发送了许多请求,并且foreach继续进行,没有我获得回应的信息。
例如:
foreach (DataLoader.GetInfo items in listBoxFetInfo.Items)
{
DownloadInfo(items.CompanyName);
}
和
void DownloadInfo(string name)
{
int requestId = feed.SendCompanyNameRequest(symbol.ToUpper(), sendType, sendTimePeriod, sendDateFrom, DateTime.Now);
}
和
feed.RequestCompanyName += new IFeedEvents_RequestCompanyNameEventHandler(feed_RequestName);
和
void feed_RequestName(int originalRequestId, short ResponseCode, string symbol, short symbolStatusCode, object records)
{
//save to file
}
我无法使用Start Multiple Async Tasks and Process Them As They Complete ,因为此解决方案需要添加CancellationToken,我无法添加(不能无效feed_RequestName
这个问题可以解决另一个问题吗?
另外,我无法更改签名:
feed_RequestName(int originalRequestId, short ResponseCode, string symbol, short symbolStatusCode, object records)
和
feed.SendCompanyNameRequest(symbol.ToUpper(), sendType, sendTimePeriod, sendDateFrom, DateTime.Now);
答案 0 :(得分:0)
你可以使用while而不是foreach吗?
像:
while(not done processing all requests) {
//grab and process next request
}
答案 1 :(得分:0)
我在黑暗中捅了一下你的事情如何运作,但这就是我要做的。由于您无法修改签名,因此您无法使用Task
,就像您提出的last question一样。
我在这里看到的是,您有一个方法可以开始请求,然后是一个在请求完成时调用的事件。我假设您的请求是在单独的线程上运行的,或者是feed
所在的库内的某个东西。您需要做的是等待该事件完成一次,然后再继续下一个项目。如果您的问题不在于您的问题或图书馆的运作方式,请与我们联系。
如果您不并行执行请求(意味着一次只执行一个请求而其他人没有使用您的feed
对象),您可以使用{{1} } class让你的一个方法非常容易依赖于另一个方法。你能做的是以下几点:
在System.Threading.ManualResetEvent
方法中,DownloadInfo
Reset
,以便每当有人拨打ManualResetEvent
时,它都会"阻止"线程并阻止它继续下去。它会等到其他人在WaitOne
上调用Set
。
在调用获取ManualResetEvent
的方法后,请致电requestId
上的WaitOne
。这将等到"其他人"在ManualResetEvent
上调用Set
。
完成处理后,在ManualResetEvent
方法中,feed_RequestName
手动重置事件。这将使您在步骤2中调用的Set
停止阻止并继续。如果您在调用WaitOne
之前将请求的结果存储在这些内容所包含的对象的某些变量中,则可以在Set
后的DownloadInfo
方法中访问结果。
一个简短的,不完整的例子:
WaitOne
重要提示:如果您的class YourClassWhereYouPutTheseThings
{
private ManualResetEvent _mre = new ManualResetEvent(true);
//...your other stuff here...
public YourClassWhereYouPutTheseThings()
{
//...your existing stuff
feed.RequestCompanyName += new IFeedEvents_RequestCompanyNameEventHandler(feed_RequestName);
//...your existing stuff
}
void YourMethod()
{
foreach (DataLoader.GetInfo items in listBoxFetInfo.Items)
{
DownloadInfo(items.CompanyName);
}
}
void DownloadInfo(string name)
{
this._mre.Reset(); //make everyone listening to _mre wait until Set is called
int requestId = feed.SendCompanyNameRequest(symbol.ToUpper(), sendType, sendTimePeriod, sendDateFrom, DateTime.Now);
this._mre.WaitOne(); //wait for the feed_RequestName method to be called once
}
void feed_RequestName(int originalRequestId, short ResponseCode, string symbol, short symbolStatusCode, object records)
{
//save to file
//store your information on the object somewhere if you would like
//after saving to your file, set the manualresetevent so that the WaitOne() above can proceed
this._mre.Set();
}
}
在可以同时执行的多个对象之间共享,则需要确保不要通过其他对象进行插入请求作为您feed
方法的请求。任何请求都会导致调用DownloadInfo
方法,因此您需要确定该方法的哪个调用与您的请求相对应。以下是关于如何开展工作的一个建议:
feed_RequestName
存储在requestId
DownloadInfo
可以访问的地方。如果在调用方法有机会执行之前调用feed_RequestName
,则可能会出现问题。你需要找到解决这个问题的方法。feed_RequestName
中,与已存储的请求ID进行比较,只有在feed_RequestName
匹配时才会调用Set
。另一个注释:您的图书馆适合并行执行请求。在进入下一个请求之前等待请求完成是非常低效的。你真正应该做的是像(伪代码):
ManualResetEvent