C# 在Foreach中等待异步事件完成
我如何使用foreach向服务器发送请求,当我得到响应时,foreach将等待返回的信息进行处理,然后再继续下一个请求 我的问题是:在foreach中,我发送了许多请求,而foreach没有处理我得到的响应信息 例如:C# 在Foreach中等待异步事件完成,c#,C#,我如何使用foreach向服务器发送请求,当我得到响应时,foreach将等待返回的信息进行处理,然后再继续下一个请求 我的问题是:在foreach中,我发送了许多请求,而foreach没有处理我得到的响应信息 例如: foreach (DataLoader.GetInfo items in listBoxFetInfo.Items) { DownloadInfo(items.CompanyName); } 及 及 及 我无法使用,因为此解
foreach (DataLoader.GetInfo items in listBoxFetInfo.Items)
{
DownloadInfo(items.CompanyName);
}
及
及
及
我无法使用,因为此解决方案需要添加CancellationToken,其中我无法添加(不能在void feed\u RequestName中添加)
这个问题还有什么解决办法
此外,我不能更改以下人员的签名:
feed_RequestName(int originalRequestId, short ResponseCode, string symbol, short symbolStatusCode, object records)
及
你能用while代替foreach吗 比如:
关于你的东西是如何工作的,我在这里暗中试探,但这是我要做的。因为你不能修改签名,你不能像你建议的那样使用
任务
我在这里看到的是,您有一个方法开始一个请求,然后在请求完成时调用一个事件。我假设您的请求运行在一个单独的线程上,或者运行在feed
所在的库中。您需要做的是等待该事件完成一次,然后再继续下一项。如果这不是你要问的问题或者你的库是如何工作的,请告诉我
如果您不是并行执行请求(意味着一次只执行一个请求,没有其他人使用您的提要
对象),则可以使用System.Threading.ManualResetEvent
类使一个方法非常容易地依赖于另一个方法。您可以执行以下操作:
DownloadInfo
方法中,Reset
重置ManualResetEvent
,这样每当有人调用WaitOne
,它都会“阻止”线程并阻止它继续运行。它会等到有人调用ManualResetEvent
上的Set
请求ID的方法后,在ManualResetEvent
上调用WaitOne
。这将等待“其他人”在ManualResetEvent
上调用Set
feed\u RequestName
方法中,Set
一旦完成处理,就会设置手动重置事件。这将使您在步骤2中调用的WaitOne
停止阻塞并继续。如果您在调用Set
之前将请求的结果存储在这些东西所在的对象上的一些变量中,y您可以在WaitOne
之后通过DownloadInfo
方法访问结果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();
}
}
重要提示:如果您的提要
在多个可以同时执行的对象之间共享,您需要确保不会将其他对象的请求与您的DownloadInfo
方法发出的请求进行交互。任何请求都会导致调用您的提要\u RequestName
方法o您需要找出该方法的哪个调用与您的请求相对应。以下是一条如何使该方法起作用的建议:
DownloadInfo
中获得的requestId
存储在feed\u RequestName
可以访问的地方。如果在调用方法有机会执行之前调用了feed\u RequestName
,则可能会出现问题。您需要找出解决此问题的方法feed_RequestName
中,与存储的请求id进行比较,如果匹配,仅调用ManualResetEvent
上的Set
我想我们可能需要更多的信息。什么是
DataLoader
列表中项目的信息当我单击“开始”时,我的程序没有响应,可能是因为在主类中我创建了void:public void SetMre(){u mre.Set();}在另一个类中的feed_RequestName中使用它。这是真的吗?您如何编写和使用它,thanx很多,但有一些功能:当我启动程序时,我的程序没有响应。我可以在另一个线程中启动这个吗?例如在foreach中,我有:this.Dispatcher.BeginInvoke(新线程启动(委托{ProgressDataLoad.Value++}));这不起作用主要的问题是:我发送了大约1000个请求,但可以发送大约250个,现在这个问题-因为工作没有问题)提供<代码>提要的库是什么?我在这个答案中展示的方法只有在库启动另一个线程来执行请求时才有效。据猜测,该库正在线程池上启动线程或执行作业。您需要使用调试器并逐步查看是否正在调用feed\u RequestName
方法,并确定何时调用该方法。
void feed_RequestName(int originalRequestId, short ResponseCode, string symbol, short symbolStatusCode, object records)
{
//save to file
}
feed_RequestName(int originalRequestId, short ResponseCode, string symbol, short symbolStatusCode, object records)
feed.SendCompanyNameRequest(symbol.ToUpper(), sendType, sendTimePeriod, sendDateFrom, DateTime.Now);
while(not done processing all requests) {
//grab and process next request
}
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();
}
}
DownloadItems:
Lock the object so that only one person uses the method at a time
foreach item in requests
call your start request method and get the id
put the id into a thread-safe set stored on the object
wait for the set to become empty
feed_RequestName:
Do your thing that you've been doing
Remove the id from the thread safe set