AsyncCallback передача параметров
HttpWebRequest^ aaa....
...
aaa->BeginGetResponse(gcnew AsyncCallback(this, &Callback), aaa);
Сам калбек:
private: void Callback(IAsyncResult^ result) {
Обработка...
...
Тут требуется обработать one
}
В случае MC++ вам придется создать класс, в в экземпляре которого разместить требуемые данные (aaa и one) и передать его tag-ом в BeginGetResponse.
Оба варианта не подойдут, идёт разбор текста, по циклу aaa приобретает значение, потом идёт вызов колбека (ну по коду который выше в общем) , данный цыкл продолжает ити, дело в том что у меня сейчас и сделано так как вы написали, но калбек на то и создал что бы работать асинхронно, вот и выходит что aaa приобрела значение, произошел вызов калбека, ааа приобрела значение, произошёл вызов калбека, но калбеки не успевают обрабатываться с такой же скоростью как и проход по цыклу, из-за этого 2 вызова калбека получат последнее значение ааа
Оба варианта не подойдут...
Что мешает делать копию того, чего у вас там меняется?
И при том HttpWebRequest вроде бы только один асинхронных запрос поддерживает. Разве нет?
З.Ы. Опять же, телепаты в отпуске (и я тоже туда скоро, ага), так что показывайте код.
Нет
Некоторое вырезаю дабы уменьшить код
ready - считывает страницу, отдает контент переменно page_content в классе
this->pattern - переменная, шаблон поиска
this->aaa - вот это та передаваемая переменная
ready(this->textBox1->Text+"/");
Regex^ rx = gcnew Regex( this->pattern, static_cast<RegexOptions>(RegexOptions::Compiled | RegexOptions::IgnoreCase) );
MatchCollection^ matches = rx->Matches( this->page_content );
for each (Match^ match in matches) {
id = Convert::ToString(match->Groups[1]->Value);
this->aaa = Convert::ToString(match->Groups[2]->Value);
HttpWebRequest^ aaa = dynamic_cast<HttpWebRequest^>(WebRequest::Create( this->textBox1->Text + "/" + id + ".html" ));
aaa->KeepAlive = false;
aaa->BeginGetResponse(gcnew AsyncCallback(this, &Callback), aaa);
}
}
private: void Callback(IAsyncResult^ result) {
HttpWebRequest^ responses = dynamic_cast<HttpWebRequest^>(result->AsyncState);
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(responses->EndGetResponse(result));
Stream^ dataStream = resp->GetResponseStream();
StreamReader^ reader = gcnew StreamReader( dataStream, encoding );
String ^responseFromServer = reader->ReadToEnd();
/* Ну и так дальше, this->aaa уже принимает не правильные значения */
}
Вы на каждой итерации каждый раз создаете новый реквест (что в принципе и нужно делать). HttpWebRequest.BeginGetResponse поддерживает только один асинхронный вызов (ссылку я приводил).
Повторяю снова:
Ну так он и передаст HttpWebRequest объект
Ну так он и передаст HttpWebRequest объект
Мне повторить в третий раз?
Если вам нужно передать еще один объект - нужно создавать класс для передачи всего набора (или использовать System.Tuple в .NET 4.0).
А сорри, понял, понял)) Спасибо большое!)
Как бы возвращает false в калбеке(просто завершает работу функции)
Вот допустим:
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(responses->EndGetResponse(result));
Мне выведет 20 Ок!(то есть все), а
MessageBox::Show("Ок!", "Внимание!");
Лишь 2???
allDone->Set(); в конец калбека, и
allDone->WaitOne(); после его вызова, вывод 20 Ок!, но теперь поочерёдно вызывается, то есть нет многопоточности
Что такое responses ?
HttpWebRequest^ responses = dynamic_cast<HttpWebRequest^>(result->AsyncState);
HttpWebRequest^ responses = dynamic_cast<HttpWebRequest^>(result->AsyncState);
Что-то странное у вас с именами переменных. Если экземпляр класса HttpWebRequest называется responses, да при том во множественном числе. Далее, вы хотите дождаться выполнения всех асинхронных операций. Что мешает при получении результата асинхронной операции (то что вертает BeginXXX) создавать и сохранять Event в некой коллекции для последующего вызова Wait (этот Event естественно передавать в колбэк)?
Класс для передачи параметров:
public string Url { get; set; }
public ManualResetEvent Event { get; set; }
public WebRequest Request { get; set; }
}
Код, запускающий операции:
foreach(var url in urls) {
var evt = new ManualResetEvent();
async_events.Add(evt);
var request = WebRequest.Create(url);
request.BeginGetResponse(Callback, new AsyncRequestInfo { Url = url, Event = evt, Request = request});
}
// ждем завершения асихнронных операций
foreach(var evt in async_events)
evt.WaitOne();
Ваш колбэк:
var response = info.Request.EndGetResponse(async);
// обрабатывем ответ
...
// сообщаем о завершении операции
info.Event.SetEvent();
З.Ы.Псевдокод писал в браузере.
Если ставить:
То появляется:
var response = info.Request.EndGetResponse(async);
// обрабатывем ответ
...
// сообщаем о завершении операции
info.Event.SetEvent();
Так вот, если сделать так:
var response = info.Request.EndGetResponse(async);
// Тут я из своего взял, делал на c++
if ( response != nullptr ) {
MessageBox::Show("Close", "Анализ");
response->Close();
}
MessageBox::Show("Обработка", "Анализ");
// обрабатывем ответ
...
// сообщаем о завершении операции
info.Event.SetEvent();
То сообщение "Обработка" выводится только когда resp!=nullptr, то есть после сообщения "Close"
То сообщение "Обработка" выводится только когда resp!=nullptr, то есть после сообщения "Close"
Как написано - так и выполяется. :D
Я-то тут при чем. ;)
Сообщение "Обработка" должна быть постоянно при вызове калбека?
Откуда мне-то знать :) Я вам пример кода показал. Когда, где и какие сообщения показывать пользователю - решать вам.
Эти сообщения для отладки, что бы показать что по калбеку всему не проходит, а только до вызова var response = info.Request.EndGetResponse(async);
А знак вопроса случайно поставил
public: static ManualResetEventSlim^ Event = gcnew ManualResetEventSlim( false );
public: static HttpWebRequest^ result;
};
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
List<ManualResetEventSlim^>^ EventAll = gcnew List<ManualResetEventSlim^>( false );
ManualResetEventSlim^ evt = gcnew ManualResetEventSlim( false );
EventAll->Add(evt);
HttpWebRequest^ aaa = dynamic_cast<HttpWebRequest^>(WebRequest::Create( "http://www.google.com" ));
aaa->KeepAlive = false;
CallBuff ^callbuffs = gcnew CallBuff;
callbuffs->Event = evt;
callbuffs->result = aaa;
aaa->BeginGetResponse(gcnew AsyncCallback(this, &grabber_graf::Form1::ResponseCallback), callbuffs);
evt = gcnew ManualResetEventSlim( false );
EventAll->Add(evt);
aaa = dynamic_cast<HttpWebRequest^>(WebRequest::Create( "http://microsoft.com" ));
aaa->KeepAlive = false;
callbuffs = gcnew CallBuff;
callbuffs->Event = evt;
callbuffs->result = aaa;
aaa->BeginGetResponse(gcnew AsyncCallback(this, &grabber_graf::Form1::ResponseCallback), callbuffs);
for each(ManualResetEventSlim^ evt in EventAll) {
evt->Wait();
}
}
//Калбек
private: void ResponseCallback(IAsyncResult^ result) {
CallBuff ^callbuffs = dynamic_cast<CallBuff^>(result->AsyncState);
HttpWebRequest^ Request = dynamic_cast<HttpWebRequest^>(callbuffs->result);
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(Request->EndGetResponse(result));
MessageBox::Show("Код исполняется!", "Анализ страниц");
resp->Close();
callbuffs->Event->Set();
}
Как видно, должно выполнится 2 запроса, но на деле идёт только 1, и программа зависает, если закоментировать код там где обращаемся к майкрософту - всё норм, что интерестно ошибка в EndGetResponse, то есть первый раз срабатывает, но на второй и более просто калбек прекращает работать когда дойдёт до строчки с EndGetResponse