2013-02-08 2 views
2

Я написал класс, который должен обеспечивать базовое взаимодействие с сервером NodeJS. Этот класс также включает экземпляр TcpClient и работает асинхронно (такие методы, как BeginRead, BeginWrite, ...), поэтому многие функции принимают обратные вызовы (анонимную функцию с использованием lambda expr.) В качестве аргумента. Проблема начинается в этом сценарии (я пытаюсь проиллюстрировать в коде мира, подобном оригиналу).C# Странное поведение обратных вызовов делегатов

this._nodeJS.Send("DATA_TO_SEND", (Response) => { 
    Console.WriteLine(Response); 

    // Section1 
    this._nodeJS.Send("ANOTHER_DATA", (Response1) => { 
     Console.WriteLine(Response1); 
    }); 
}); 

Проблема возникает в section1. Когда он закомментирован, программа ведет себя так, как ожидалось. Ответ получен в Консоли. Когда он не прокомментирован, он начинает вести себя очень странно. Write to Console в разделе 1 не работает (во многих случаях) и, что важно, код ниже Console.WriteLine в этом разделе не выполняется, «поток» просто останавливается прямо перед командой. Я попытался отлаживать его, шаг за шагом, переменные в Разделе 1 правильно установлены, и когда я перехожу к следующей команде, отладка просто прекращается. Что-то не так с этим подходом? Есть ли какие-то вещи, о которых я должен знать?

Для лучшего воображения здесь приведен пример. Я подключаюсь к серверу NodeJS, когда это делается, я отправляю запрос и жду ответа, содержащие данные, которые обрабатываются и снова отправляются на сервер NodeJS в следующем запросе (раздел 1). NodeJS дает мне окончательный ответ и работает программа ... Спасибо за любой совет!

+0

Возможно, вы захотите избавиться от объекта '_nodeJS' после отправки и перед обратным вызовом или присвоить новое значение этой переменной? Попробуйте создать новый объект nodeJS внутри первого обратного вызова, который будет использоваться при отправке второго 'Send', по крайней мере для диагностики, если не в вашей окончательной программе. – Servy

+0

Спасибо за быстрый ответ. Согласно моему исходному источнику, экземпляр NodeJS хранится в шаблоне реестра, поэтому есть только один экземпляр NodeJS. Когда я отлаживал его и входил в раздел1, каждая переменная имела правильное значение, каждый из них. –

ответ

1

Наконец, я понял, что происходит. Я знаю, я не показываю свой исходный код и вместо этого использовал какой-то псевдокод, но если кому-то интересно узнать, проблема, вероятно, вызывала неправильное преобразование полученных данных. У меня есть буфер размером 1024 и StringBuilder переменная, в которой были добавлены данные. Поэтому, когда я получил данные, преобразовал их так: Encoding.UTF8.GetString(state.Buffer) - это неправильно, вместо этого мне пришлось использовать Encoding.UTF8.GetString(state.Buffer, 0, bytesRead). Я не знаю, как, но эта часть кода вызывала проблемы и останавливала обратный вызов для выполнения.

0

Не зная подробностей реализации, я подозреваю, что второй звонок _nodeJS.Send(... блокируется ответом от первого вызова «Отправить».

В догадке, ваш код делает что-то вроде этого (сделанный до псевдокода!):

void Send(String data, Action<Response> callback) 
{ 
    _socket.BeginSend(Magic(data), r => { 
     callback.Invoke(r.ResponseData); 
     _socket.EndSend(r.Result); //you cannot call _socket.Send() again until you have done this! 
    }); 
} 

Благодаря порядку операций, он должен делать это:

void Send(String data, Action<Response> callback) 
{ 
    _socket.BeginSend(Magic(data), r => { 
     _socket.EndSend(r.Result); 
     callback.Invoke(r.ResponseData); 
    }); 
} 
+0

Спасибо. Так я это сделал. В функции отправки я вызываю EndWrite в NetworkStream, а затем вызываю свой обратный вызов. Id хотел бы выделить, что вторая функция Send вызывается после успешного получения ответа, и все переменные, включая переменную Response1, содержат правильные данные. Проблема в том, что когда я находил источник проблемы и отлаживал этот код в разделе1, «Thread», который выполнял код Console.WriteLine (Response1) и другие, просто останавливался. Кажется, он был остановлен другой нитью, это действительно странно для меня. –

+0

@TomasPetovsky делает это, если вы вынимаете только 'Console.Writeline();' звонки? Вы можете просто увеличить целое поле, чтобы проверить его вызов. – Pondidum

+0

да, это работает, я понял, что Console.WriteLine(); во многих случаях начинает работать, когда я использую Console.WriteLine(); в каждой функции обратного вызова, которая выполняется в текущем потоке.Но мне действительно не нужно ничего писать в WriteLine, это просто для целей отладки, что заставляет меня грустить, если casct, что код в разделе 1 (в оригинальной версии у меня есть console.writeline и много строк кода) просто прекращает выполнение ! Он ведет себя так, как будто он был остановлен каким-то другим законченным обратным вызовом или чем-то еще. Я действительно не знаю. –

Смежные вопросы