Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

AsyncCallback передача параметров

54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
В общем возможно ли передать через AsyncCallback параметры, дело в том что мне надо передать 1 переменную. Пример:

Код:
String ^one = "Раз раз раз";
HttpWebRequest^ aaa....
...
aaa->BeginGetResponse(gcnew AsyncCallback(this, &Callback), aaa);


Сам калбек:
private: void Callback(IAsyncResult^ result) {
Обработка...
...
Тут требуется обработать one
}
5
02 июля 2010 года
hardcase
4.5K / / 09.08.2005
Если бы вы использовали C#, то очевидным решением стали бы замыкания.
В случае MC++ вам придется создать класс, в в экземпляре которого разместить требуемые данные (aaa и one) и передать его tag-ом в BeginGetResponse.
54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
hardcase
Оба варианта не подойдут, идёт разбор текста, по циклу aaa приобретает значение, потом идёт вызов колбека (ну по коду который выше в общем) , данный цыкл продолжает ити, дело в том что у меня сейчас и сделано так как вы написали, но калбек на то и создал что бы работать асинхронно, вот и выходит что aaa приобрела значение, произошел вызов калбека, ааа приобрела значение, произошёл вызов калбека, но калбеки не успевают обрабатываться с такой же скоростью как и проход по цыклу, из-за этого 2 вызова калбека получат последнее значение ааа
5
02 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
hardcase
Оба варианта не подойдут...

Что мешает делать копию того, чего у вас там меняется?
И при том HttpWebRequest вроде бы только один асинхронных запрос поддерживает. Разве нет?


З.Ы. Опять же, телепаты в отпуске (и я тоже туда скоро, ага), так что показывайте код.

54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
Цитата:
И при том HttpWebRequest вроде бы только один асинхронных запрос поддерживает. Разве нет?


Нет

Некоторое вырезаю дабы уменьшить код
ready - считывает страницу, отдает контент переменно page_content в классе
this->pattern - переменная, шаблон поиска
this->aaa - вот это та передаваемая переменная

Код:
private: void Doread(void) {
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 уже принимает не правильные значения  */
}
5
02 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
Нет


Вы на каждой итерации каждый раз создаете новый реквест (что в принципе и нужно делать). HttpWebRequest.BeginGetResponse поддерживает только один асинхронный вызов (ссылку я приводил).


Повторяю снова:

 
Код:
aaa->BeginGetResponse(gcnew AsyncCallback(this, &Callback), aaa);
Вместо aaa последним параметром нужно передать некий объкт который будет содержать нужную информацию и этот ваш экземпляр HttpWebRequest для корректного завершения асинхронной операции.
54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
hardcase
Ну так он и передаст HttpWebRequest объект
5
02 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
hardcase
Ну так он и передаст HttpWebRequest объект


Мне повторить в третий раз?
Если вам нужно передать еще один объект - нужно создавать класс для передачи всего набора (или использовать System.Tuple в .NET 4.0).

54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
hardcase
А сорри, понял, понял)) Спасибо большое!)
54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
Ну что я могу сказать... Вы гений)) Спасибо за помощь) Всё работает! Тему можно закрыть)
54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
Хотя нет, что бы не создавать тему, почему строка
 
Код:
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(responses->EndGetResponse(result));

Как бы возвращает false в калбеке(просто завершает работу функции)

Вот допустим:
 
Код:
MessageBox::Show("Ок!", "Внимание!");
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(responses->EndGetResponse(result));

Мне выведет 20 Ок!(то есть все), а
 
Код:
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(responses->EndGetResponse(result));
MessageBox::Show("Ок!", "Внимание!");


Лишь 2???
54K
02 июля 2010 года
Lion__
22 / / 13.05.2010
Добавил
allDone->Set(); в конец калбека, и
allDone->WaitOne(); после его вызова, вывод 20 Ок!, но теперь поочерёдно вызывается, то есть нет многопоточности
5
02 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
Хотя нет, что бы не создавать тему, почему строка
 
Код:
HttpWebResponse^ resp = dynamic_cast<HttpWebResponse^>(responses->EndGetResponse(result));
Как бы возвращает false в калбеке(просто завершает работу функции)

Что такое responses ?

54K
03 июля 2010 года
Lion__
22 / / 13.05.2010
Я же давал код выше:
 
Код:
private: void Callback(IAsyncResult^ result) {
HttpWebRequest^ responses = dynamic_cast<HttpWebRequest^>(result->AsyncState);
5
03 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
Я же давал код выше:
 
Код:
private: void Callback(IAsyncResult^ result) {
HttpWebRequest^ responses = dynamic_cast<HttpWebRequest^>(result->AsyncState);


Что-то странное у вас с именами переменных. Если экземпляр класса HttpWebRequest называется responses, да при том во множественном числе. Далее, вы хотите дождаться выполнения всех асинхронных операций. Что мешает при получении результата асинхронной операции (то что вертает BeginXXX) создавать и сохранять Event в некой коллекции для последующего вызова Wait (этот Event естественно передавать в колбэк)?

54K
03 июля 2010 года
Lion__
22 / / 13.05.2010
Ничего не понял) Заумно сказали)
5
03 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
Ничего не понял) Заумно сказали)


Класс для передачи параметров:

 
Код:
class AsyncRequestInfo {
    public string Url { get; set; }
    public ManualResetEvent Event { get; set; }
    public WebRequest Request { get; set; }
}

Код, запускающий операции:
Код:
var async_events = new List<ManualResetEvent>();

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 info = (AsyncRequestInfo)async.State;

var response = info.Request.EndGetResponse(async);
// обрабатывем ответ
...

// сообщаем о завершении операции
info.Event.SetEvent();


З.Ы.Псевдокод писал в браузере.
54K
09 июля 2010 года
Lion__
22 / / 13.05.2010
идёт зависание после того как прошло по всем страницам. В async_events всего 1 элемент
54K
09 июля 2010 года
Lion__
22 / / 13.05.2010
В отладчике:
Цитата:
"A first chance exception of type 'System.ArgumentException' occurred in System.dll"



Если ставить:

 
Код:
Threading::Thread::Sleep(1000);

То появляется:
Цитата:
The thread '<No Name>' (0x****) has exited with code 0 (0x0).

54K
09 июля 2010 года
Lion__
22 / / 13.05.2010
В калбеке фигня, вот возьмом ваш пример:

 
Код:
var info = (AsyncRequestInfo)async.State;

var response = info.Request.EndGetResponse(async);
// обрабатывем ответ
...

// сообщаем о завершении операции
info.Event.SetEvent();


Так вот, если сделать так:

Код:
var info = (AsyncRequestInfo)async.State;

var response = info.Request.EndGetResponse(async);
// Тут я из  своего взял, делал на c++
if ( response != nullptr ) {
    MessageBox::Show("Close", "Анализ");
    response->Close();
}
MessageBox::Show("Обработка", "Анализ");

// обрабатывем ответ
...

// сообщаем о завершении операции
info.Event.SetEvent();


То сообщение "Обработка" выводится только когда resp!=nullptr, то есть после сообщения "Close"
5
09 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__

То сообщение "Обработка" выводится только когда resp!=nullptr, то есть после сообщения "Close"


Как написано - так и выполяется. :D
Я-то тут при чем. ;)

54K
09 июля 2010 года
Lion__
22 / / 13.05.2010
Цитата:
Как написано - так и выполяется.


Сообщение "Обработка" должна быть постоянно при вызове калбека?

5
09 июля 2010 года
hardcase
4.5K / / 09.08.2005
Цитата: Lion__
Сообщение "Обработка" должна быть постоянно при вызове калбека?



Откуда мне-то знать :) Я вам пример кода показал. Когда, где и какие сообщения показывать пользователю - решать вам.

54K
09 июля 2010 года
Lion__
22 / / 13.05.2010
hardcase
Эти сообщения для отладки, что бы показать что по калбеку всему не проходит, а только до вызова var response = info.Request.EndGetResponse(async);

А знак вопроса случайно поставил
54K
14 июля 2010 года
Lion__
22 / / 13.05.2010
Недавно был похожий пост, его не решил, в этот раз вылаживаю небольшой код, который не работает, прошу найти ошибку:


Код:
public ref class CallBuff {
    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
54K
01 августа 2010 года
Lion__
22 / / 13.05.2010
Я так понял ответа никто не знает?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог