I have created a TelNet server for a project I need to do which is working fine, however when a client connects to the server it needs to connect to a database, again this works fine when the connection information is correct and/or calls to the database do not take too long.
If the database call takes a long time (usually due to incorrect credentials or a badly optimised stored procedure) the server will crash with a Windows error message (i.e. not debuggable), which I understand is the underlying TCP system kicking in, which is fine. To resolve this I am putting all the database calls into BackgroundWorkers, so the server (and clients) continue to work, however I need to kill off this process if it is obviously taking too long.
I know about using BackgroundWorker.CancellationPending, but as this is a single method call to the database (via and external DLL), it will never get checked. Same issue with a self-made approach that I have seen elsewhere. The other option I have seen is using Thread.Abort(), but I also know that is unpredictable and unsafe, so probably best not to use that.
Does anyone have any suggestions how to accomplish this?
The problem here is that an external DLL is controlling the waiting. Normally, you could cancel ADO.NET connections or socket connections but this doesn't work here.
Two reliable approaches:
Move the connection into a child process that you can kill. Kill is safe (in contrast to Thread.Abort!) because all state of that process is gone at the same time.
Structure the application so that in case of cancellation the result of the connection attempt is just being ignored and that the app continues running something else. You just let the hanging connection attempt "dangle" in the background and throw away its result when it happens to return later.
Related
I'm not sure how to approach this. I am hesitant about showing my code because it's a university assignment. I need some place to start.
I'm making a TCP card game with four players and a server. Every 100ms, a player asks for an update from the server using a background worker. The server accepts a client connection and reads in a Enumeration value (sent as an Int32) that tells it the action it wants server to send it (update, card, player, etc) and a value that is read in based on the Enumeration value (Recieving an Update Enumeration means it needs to read in a Int32 next). The server sends back a response based on the Enumeration read in.
Here's where the problem occurs. I have a custom built computer (2500K processor, Win8 x64) and when I execute the program on it, it will loop forever, accepting client requests and sending the appropriate response back. Exactly as expected! However, on my laptop (Levono YogaPad, Win8 x64) the back and forth exchange lasts for around 30-50 requests and then deadlocks. It's always at the same spot. The server has read in the Enumeration and is awaiting for the second value. The client is past the part of sending the enum and value and is waiting for the results. It is always stable on my desktop and always deadlocks on my laptop. I even slow the program down to update every second and it still deadlocks. I'm not sure what to do.
I've built the program on each computer. I've built the program on my desktop and ran it on my laptop and it still deadlocks. Does anyone have any suggestions?
Many thanks!
You are lucky that the code hangs on one machine before you send the assignment in and it hangs on your teachers machine. You are also lucky that the problem is reproducible, so better find out where exactly it hangs. Without having access to the code I have the following wild guesses:
you forgot to do proper error handling in all places and now it busy loops because of an unexpected error
it hangs inside a read where you try to read N bytes but the peer sends only K<N bytes
These are wild guesses, but without having access to even the basic structure of your program you cannot probably expect anything more.
Actually I am confuse about one thing.
I have .net application and using sql server 2008 for database.
Now, on my Method A i am filling datareader.
now, during while loop i am calling another method B by pass one property of result.
at that time i also open DB connection & close it.
same thing doing Calling another method C from method B.
at that time also open DB connection & close.
To fill final list of Method A. it is taking time.
so, my point is.To open DB connection & closing it. Is it time consuming process?
To open DB connection & closing it. it is time consuming process
Yes. If pooling is enabled and the connection is returned from the pool then opening and closing costs at least one round-trip, to reset the connection. If the connection is not pooled opening and closing is a full SSPI complete handshake. If SQL authentication is used and encryption is enabled, there is another complete SSL handshake to establish a secure channel before the SQL handshake. Even under ideal conditions, it takes 10s of ms, it can go up to whole seconds with some minimal network latency added.
A well written ASP.Net application needs one (pooled) connection per request, never more.
It is generally very bad practice to connect to a third part application (database, WebService or similar) in any kind of loop. Communication like this is always takes a relatively long time.
As the number of elements in the loop increases the application will become exponentially slower and slower.
A much better approach is to perform an operation for all the elements then pass the required data into your loop logic.
As with all things there are exceptions, loops where you have millions of entities to process and the connection is a small overhead may create circumstances where it's more efficient to process each entity atomically.
I have a windows service which receives messages via RabbitMQ, this triggers an event handler which does some work and then attempts to persist the result to the database. It's threaded using:
ThreadPool.QueueUserWorkItem(ProcessMessageOnThread, messageReceived);
where ProcessMessageOnThread is a method which does the work on the messageReceived which is a representation of the message dequeued from RabbitMQ.
Under normal circumstances the windows service operated as expected, that is dequeue, process and persist.
I want to ensure that all of my messages are processed and given a fair change to be processed so if I can't open a connection to SQL Server I simply requeue the message for it to be processed again (hopefully that time the SQL Server will be back, otherwise this continues - and I'm fine with that).
Now the problem comes when the process has been running as expected for a period of time, the SQL Server connection pool has filled up and then SQL Server is disconnected, now this is when things get a bit unstable.
One of two things can happen:
An exception is thrown on connection.Open() - however I'm catching this and so not worried about it
An exception is thrown on cmd.ExecuteNonQuery() - which is where I'm executing a stored procedure
It is the second option that I need to figure out how to handle. Previously I assumed that any exception here meant that there was a problem with the data I was passing into the stored procedure and therefore should just move it out of the queue and have something else analyse it.
However, now I think I need a new approach to handle the cases where the exception is to do with the connection not actually being established.
I've had a look at the SqlException class and noticed a property called Class which has this description Gets the severity level of the error returned from SQL Server, now the info on this says:
Messages with a severity level of 10 or less are informational and indicate problems caused by mistakes in information that a user has entered. Severity levels from 11 through 16 are generated by the user, and can be corrected by the user. Severity levels from 17 through 25 indicate software or hardware errors. When a level 17, 18, or 19 error occurs, you can continue working, although you might not be able to execute a particular statement.
Does this mean to fix my exception handling I can just check if (ex.Class > 16) then requeue message because the problem is with the connection else throw it away as it is most likely to do with malformed data being send to the stored procedure?
So the question is, how should I do exception handling and how can I detect when calling cmd.ExecuteNonQuery() if the exception thrown is because of a disconnected connection.
Update:
I've experienced problems previously with connections not being returned to the pool (this was due to threading issues) and have fixed those problems, so I'm confident the issue isn't to do with connections not going back into the pool. Also, the logic around what the connections are being used for is so simple also I'm ensuring they are closed consistently...so I'm more interested in answers to do with the disconnection of the Sql Server and then the capturing the behaviour of cmd.ExecuteNonQuery()
Connections in the connection pool can get into a weird state for various reasons, all of which have to do with poor application design:
Closing the connection before its associated data reader
Change a setting (like transaction isolation level) that the pool does not reset
Starting an asynchronous query (BeginOpenReader) and then returning the connection to the pool before the asynchronous handler fires
You should investigate your application and make sure connections are properly returned to the pool. One thing that can help debugging is reducing the size of the application pool in a development setting. You change the size of the pool in the connection string:
...;Integrated Security=SSPI;Max Pool Size=2;Pooling=True;
This makes pooling issues much easy to reproduce.
If you can't find the cause, but still need to deploy a fix, you could use one of ClearPool or ClearAllPools. A good place to do that is when you detect one of the suspicious exceptions after Open() or ExecuteNonQuery(). Both are static methods on the SqlConnection class:
SqlConnection.ClearPool(yourConnection);
Or for an even rougher approach:
SqlConnection.ClearAllPools()
Note that this is basically Pokémon Exception Handling. If it works, you'll have no idea why. :)
I have noticed that it takes a long time in connecting to the database when executing my query. Is it possible to write an asp.net application in such way that has a database connection that is always open? Or is it better to write service and have asp.net app communicate with that service?
You can use connection pooling in order to conserve time it takes to initialize a connection. BTW, SQL-Server supports it OOTB, so you don't really have to implement it yourself.
It does not matter much which means you use to connect to the DB (ADO.NET, DAAB, etc..)
As to your second suggestion, to write a service and have the application communicate requests to it: it wont help in this scenario, since you are simply moving the problem to another process, but the accumulated time of fulfilling a request remains or even grows, considering the extra network time.
My program starts with windows startup,
But a background worker is supposed to work instantly after the program is opened.
But it starts with a delay and then even returns false signs(it returns if a site is up),
Only after about 15 seconds the background-worker continues to work normally and the program too. I think this is because of .net framework trying to load, or internet connection that is not up yet, or something that didn't load yet(windows startup).
What can solve this, and what is the probable cause? (WinForm C#)
Edit:
Here is something I thought of,
I don't think though that this is a good practice. Is there a better way?
(Load method):
while (!netConnection())
{
}
if(netConnection())
bwCheck.RunWorkerAsync();
I think this is because of .net framework trying to load
Nope. If that were the case your program wouldn't run.
or internet connection that is not up yet, or
Yup. The network card/interface/connection/whatever is not initialized and connected to the internet yet. You can't expect a PC to be connected to the internet immediately at startup. Even more, what if your customer is on a domain using network authentication? What if they delay network communications until some task is complete (this was actually the problem in my case below. Seriously.)
It may take even longer to get it up and running in that case (read: don't add a Thread.Sleep() in a vain attempt to 'fix' the issue.
I had to fix a problem like this once in a systems design where we communicated to a motion control board via the ethernet bus in a PC. I ended up adding some code to monitor the status of the network connection and, only when it was established, started talking to the device via the network card.
EDIT: As SLaks pointed out in the comments, this is pretty simple in C#: The NetworkAvailabilityChanged event for your programming pleasure.
It is absolutely because of everything still starting up. Services can still be coming online long after you log in, the quick login dialog you see was an optimization in windows to let you log in while everything else still starts up.
Take note of
How to detect working internet connection in C#?
specifically a technique that avoids the loopback adapter:
System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()