C# Strange Behaviour of Delegate Callbacks - c#

I wrote a class, that should provide basic interaction with NodeJS server. This class also includes TcpClient instance and works asynchronously (methods like BeginRead, BeginWrite, ...) so many functions takes callbacks (anonymous function using lambda expr.) as an argument. Problem starts in this scenario (I try to illustrate on a peace of code similar to original).
this._nodeJS.Send("DATA_TO_SEND", (Response) => {
Console.WriteLine(Response);
// Section1
this._nodeJS.Send("ANOTHER_DATA", (Response1) => {
Console.WriteLine(Response1);
});
});
Problem occurs in Section1. When it's commented out, program behaves as expected. Response is received a written to Console. When it's not commented out, it starts to behave very strange. Write to Console in Section1 doesn't work (in many cases) and, what is important, code below Console.WriteLine in this section is not executed, the "thread" just stops right before command. I tried to debug it, step by step, variables in Section1 are correctly set, and when I get to the next command, debugging just stops. Is there anything wrong with this approach? Is there some things I need to be aware of?
For better imagination here is my example. I connect to the NodeJS server, when it's done, I send a request and wait for response containing data, that are processed and again sent to the NodeJS server in next request (Section1). NodeJS give me final response and program works ... Thanks for any advice!

Finally, I figured out, what's goin' on. I know, I din't show my original code and instead used some kind of pseudo-code, but if someone is interested to know, problem, probably, was causing wrong conversion of received data. I have buffer of size 1024 and StringBuilder variable where the data was appended. So when I received the data, converted it this way: Encoding.UTF8.GetString(state.Buffer) - this is wrong, instead, I had to use Encoding.UTF8.GetString(state.Buffer, 0, bytesRead). I don't know how, but this part of code was causing troubles and stopping callback to execute.

Without knowing your implementation details, I would suspect that the second _nodeJS.Send(... call is being blocked by the response from the first Send call.
At a guess, your code does something like this (made up pseudocode!):
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!
});
}
Due to order of operations, it should be doing this:
void Send(String data, Action<Response> callback)
{
_socket.BeginSend(Magic(data), r => {
_socket.EndSend(r.Result);
callback.Invoke(r.ResponseData);
});
}

Related

Express Cannot set headers after they are sent

I have a situation where I am running an interactive C# console-program from node/express. The program runs in an infinite loop, accepts a string from the command-line, and echoes it back.
The following code works for the first time I call http://localhost:3000?command=hello
Next time around, Node crashes by reporting Can't set headers after they are sent.
If the move the const script = spawn('/Users/amarshanand/shadowClient/myscript.sh'); in the sendToShell(), it works, but since I have to start a new shell and the script, it takes a lot longer.
How can I make it work like start once and accept command for each request.
const express = require('express')
const app = express()
const { spawn } = require('child_process');
const script = spawn('/Users/amarshanand/shadowClient/myscript.sh');
const sendToShell = (command, done) => {
script.stdout.on('data', (stdout) => {
console.log(`stdout: ${stdout}`);
done(stdout);
});
script.stderr.on('data', (stderr) => {
console.log(`error: ${stderr}`);
});
script.stdin.write(`${command}\n`);
}
app.get('/', (req, res) => {
sendToShell(req.query.command, result => res.send(`${result}`));
})
app.get('/getstate', (req, res) => {
res.send('state');
})
app.post('/setstate:state', (req, res) => res.send('posted state'));
app.listen(3000, () => console.log('Example app listening on port 3000!'))
That particular error occurs when you try to send more than one response to an incoming request. When I examine your code, I see that this particular piece of code:
script.stdout.on('data', (stdout) => {
console.log(`stdout: ${stdout}`);
done(stdout);
});
Can receive the data event more than once and when it does, it will call done(stdout) more than once which will cause the caller to call res.send() more than once.
With streams, you have no idea how many times the data event will be called. It could be called only once or it could be called many times with lots of small pieces of data.
In addition, you only have one script that all your requests use. So, each time you call sendToShell(), you add yet another script.stdout.on('data', ...) event handler so they will pile up and you will have duplicates causing you to call done() more than once for each data event. If you're going to stick with this structure, then you need a way to know when all the data has been sent for the last command and then you need to remove that event handler so they don't pile up.
FYI, this code also has concurrency issues because multiple requests could come into your server that cause you to run a command and you'd have no idea which response belongs with which command. If you're going to keep just one shell open, they you probably need to queue commands to the shell so you don't send the next command or set up its event handlers to read the response until the previous command is done. That way you won't be reading the response from the wrong command.

Finally block not executed when using HttpClient

I'm working on an Xamarin.Forms application with MVVM. In my viewmodel I want to Get all the patients from an API. This is the code:
public async Task GetAllPatients()
{
try
{
isFetchingData = true;
var response = await httpClient.GetStringAsync(baseUrl + "/patient?query=ma");
var resultPatients =
JsonConvert.DeserializeObject<ObservableRangeCollection<PatientViewModel>>
(testJson,jsonSerializerSettings);
AllPatients.ReplaceRange(resultPatients);
Patients.ReplaceRange(resultPatients);
}
catch(Exception e)
{
Console.WriteLine("*****ERROR kon API niet ophalen");
Console.WriteLine(e.Message);
}
finally
{
CheckIfEmptyList();
isFetchingData = false;
}
}
At first I just got the API hard coded from a json string (testJson) in my code and everything went smoothly. But from the moment I put the htppClient out of commentary something strange happens (even when I don't use the variable as you can see in the code(I get the same result when I do use the variable though)).
The finally block is not executed.
It is to say, when I go and debug the app, the code goes through the finally and checks if the list is empty and puts isFetchingData to false. But I don't see that happening on the screen. If the list is empty a label should occur but now that label doesn't go away when list is not empty. The INotifyPropertyChanged does work good because without the httpClient it runs smoothly.
I'm very new to asynchronous programming so maybe I forgot to implement something that has to make sure the GetStringAsync ends properly? Maybe it keeps fetching the data and that is why I never see the finally block executed (even though it does behind the screen). I've read some articles about asynchronous programming but couldn't find something that could help me out.
I must also say that this method is called from the constructor, which makes it a little bit harder to run async. I tried calling it without async await and I tried calling it this way:
Task.Run(async ()=> { await GetAllPatients(); });
I tried with and without ConfigureAwait(false) but that doesn't make a difference either.
Finding a way to not put the method in the constructor (as suggested by CrowCoder and Albert) seemed the only possibility. In this case I managed to do so, but for other people it may not be always possible.
Because I work with MVVM without a framework and I'm very new to Xamarin and asynchronous programming (I'm a student), it was too difficult for me to find an alternative to the constructor.
I will put this as an answer, but if someone can give a code example where it would work to put the method in the constructor, or a workaround, it is still very welcome.

Reactive Extensions - Flushing Subject / IObservable in a synchronous fashion

EDIT: I've edited a few lines of code, when running in the IDE it fails without an error or anything.
I'm new to Reactive Extensions and have a problem that I am trying to sort out. I'm using RX to queue events on a machine, then every so often send that data to a server. My problem appears to be that when the application is shutting down, anything that is an async call of any sort seems to just cancel and not run, thus the last batch of events never gets sent.
I have a Subject, where Event is my data class. I know now that a Subject might not be the best class to use, but here we are.
My code looks mostly like the following, added a few comments for clarity:
IObservable<IList<Event>> eventsObserver = Instance.EventBuffer.ToList<Event>();
var eventsEnumerable = eventsObserver.ToEnumerable();
List<Event> events = new List<Event>();
try
{
events = (List<Event>)eventsEnumerable.First(); // THIS LINE FAILS SILENTLY, EVEN IN DEBUGGER...
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine("Error: " + ex.Message);
}
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(someURI);
HttpResponseMessage response = client.PostAsync(somePage, new StringContent(SerializeToJSON(events))).Result;
response.EnsureSuccessStatusCode();
}
If I don't make the call to the web server synchronous (with the '.Result'), it fails there. I've tried a lot of ways to get the data from the IObservable into something I can send, but either the code fails (usually with a bad cast of some sort), or the events are not yet put into the data structure that I want to send. I know that RX is by nature async, and I'm asking to deal with it in a synchronous way, I would figure that there would be a solution. Thanks in advance!
Supposing that you control the Observable source, you could call Observable.OnComplete() like Enigmativity has pointed out. Otherwise, you could try to keep a copy of every value received before buffering it:
Observable.Do(x => localCopy = x).Buffer(..)
This local copy would be accessible to you at shutdown.
In any case, please note that .First() is marked obsolete in the latest Rx versions, possibly to avoid the problem you are experiencing.

C#: will there be a recursion limit issue with this approach borrowed from javascript

Wondering if an approach that's possible in javascript is OK to use in C#.
In a javascript application, when a large number of web requests have to be made one after the other, the UI can be kept responsive by eschewing a for-loop, and instead, using a stack (an array) and events. The next URL is popped from the array in the success eventhandler, which keeps making another request until the stack is empty. Can a similar approach be taken in C# with a Stack? Is the following legit?
urlStack .... // stack of urls
myRequestMaker = new WebRequestMaker(); // my custom object
myRequestMaker.ResponseReceived += (s,e) =>
{
// e contains info whether the request succeeded, failed, or timed out
url = pop another url from urlStack if it's not empty
(s as WebRequestMaker).MakeWebRequest(url);
}
url = pop first url from urlStack
myRequestMaker.MakeWebRequest(url);
(The ReponseReceived event is raised by the WebRequestMaker object also when the request times out, BTW)
In javascript, you can hit maximum recursion limits using this approach, and to get around that you can wrap the method invocation, made inside the success eventhandler, in a SetTimeout. Will invokving myRequestMaker's MakeWebRequest method inside the ResponseReceived eventhandler run into analogous issues?
Yes, your code will eventually hit StackOverflowException. You can simulate setTimeout behaviour using the System.Task class that runs code asynchronously:
myRequestMaker.ResponseReceived += (s,e) =>
{
// e contains info whether the request succeeded, failed, or timed out
url = pop another url from urlStack if it's not empty
Task.Run(() => (s as WebRequestMaker).MakeWebRequest(url));
}
(of course, your urlStack now should be a concurrent to avoid racing conditions)
Optimally, you would not use the code above, but implement a MakeWebRequestAsync method that gets your job done asynchronously. Most built-in long-running/blockin methods (such as reading and writing from/to streams) in .Net already implement such a method, so if your WebRequestMaker is actually using a System.Net.WebClient you can call the async version. More information about tasks and async/await can be found in MSDN.
Yes it will, every function call pushed to the call stack and poped when it finishes.
The error you mention is fired when the call stack is full, not in javascript, in most languages (in fact I don't know any that doesn't).
You should apply the same logic as you do in Javascript here.

ASMX webservices with Silverlight Async confusion

I have a silverlight 4 web app that needs to communicate with a server by accessing the ASMX web service on the server.
I have a list(yes, the array), of objects that I need to send(one by one) as a parameter to the service. However looping through the list and running the method(objecttosend); will not work because I need to send then one after another and Silverlight seems to only support Async(presumably to not lockup interface - makes sense).
So I tried this:
public void SendNextPart()
{
if (partsToSend.Count > 0)
{
Part thisPart = partsToSend.Dequeue();
fuWS.createPartCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(fuWS_createPartCompleted);
fuWS.createPartAsync(thisPart);
}
}
Queue<Part> partsToSend = new Queue<Part>();
void fuWS_createPartCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
SendNextPart();
}
Which, as far as I can understand it, will check to see if the List has parts to send, then run the webservice(called fuWS) method and delete that part from the partsToSend List. Once it gets the completed event it should then run the SendNextPart method again and send the next part.
However what is happening(picked this up by watching HTTPwatch) is that it sends the first part, then after that is sends 2 parts at once and then after that more and more, all at once. Almost as if it is receiving the completed event before it has actually sent to the server and run the method successfully.
Please help, this is bugging the hell out of me, and it completely breaks what I need to do :'(
I don't see the SendNextBuffer method that you're calling in the web service callback event handler. But in any case, at best your code has a race condition. If the web service completes and returns before the partsToSend.RemoveAt line is executed (theoretically possible) then you could be making the next request before you've removed the one you just sent.
So first, you should check to make sure you've included all the code in your example unless you meant for SendNextBuffer to say SendNextPart.
Secondly, you should move the partsToSend.RemoveAt line before the web service call.
Finally, you should probably change the partsToSend list into a Queue<Part> (first in, first out) or Stack<Part> (last in, first out) instead since that is what you're using it as.
Ok, so after using Debug.WriteLine, I realized that I was being an idiot.
Check out this line:
fuWS.createPartCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(fuWS_createPartCompleted);
What this was doing was adding a new event handler every time it had to send a new part. So the second part sending now had two callback then the third would have more and so on increasing exponentially.

Categories