Named Pipes Server exits without warning - c#

Im trying to setup a named pipes connection between a server-software and a client.
This is my server code:
class Program
{
private static NamedPipeServerStream server = new NamedPipeServerStream("p", PipeDirection.InOut);
static void Main(string[] args)
{
Action<NamedPipeServerStream> a = callBack;
a.BeginInvoke(server, ar => { }, null);
}
private static void callBack(NamedPipeServerStream pipe)
{
pipe.WaitForConnection();
var line = "";
while (line != "exit")
{
try
{
StreamReader reader = new StreamReader(pipe);
while (line != "exit")
{
line = reader.ReadLine();
switch (line)
{
default:
foo();
break;
}
}
break;
}
catch (IOException)
{
pipe.Disconnect();
continue;
}
}
}
}
But when I try to run this application it exits directly after the start.
I have used the debugger to reach the WaitForConnection-line and then it exits without an error or an exception. And there is nothing running but the server.
It quits without getting handled by the catch-part. Am I missing anything?

The execution is blocked on WaitForConnection and will not continue until a NamedPipeClientStream object establishes a connection to the NamedPipeServerStream object.
Please have a look here (The example should help you out): https://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream(v=vs.110).aspx
EDIT: I misunderstood the problem and originally thought that the question had to do with the execution blocking from the WaitForConnection method. The code below is the addition to the actual quesiton as well as my explanation.
The problem is the way you invoke your action. As you are calling BeginInvoke it is invoked asynchronously, on a threadpool thread. Therefor you need to check if the action has finished or not otherwise the main thread keeps running and reaches the end. I have updated my answer on how you can do this very easily
Hopefully this code helps you understand why it exists! :)
Action<NamedPipeServerStream> a = callBack;
var result = a.BeginInvoke(server,ar => { },null);
while (!result.IsCompleted)
{
}

Related

C# Timeout with Solidworks VBA Macro

I have a few functions in a Solidworks Addin which call on a VBA macro (Via the runMacro2 method) a co-worker has been working on for the last few weeks. In his code he calls a Solidworks function which, under certain, unknown conditions, hangs for a long period of time. How long seems to depend upon the size and quantity of bodies in the part. Considering at least one of the functions we want to run this from i automatic, this just wont do.
I have tried using the Thread.Join(int) method (shown below) but it doesnt work. I also tried modifying the code from this answer Close a MessageBox after several seconds with the same results. Is there anything I can do either in C# or VBA to handle a timeout for this without re-writing his entire macro?
public void runBB()
{
Stopwatch testStop = new Stopwatch();
Thread workerThread = new Thread(bbRun);
testStop.Start();
workerThread.Start();
if (!workerThread.Join(50))
{
workerThread.Abort();
testStop.Stop();
MessageBox.Show("Unable to generate Bounding Box after " + testStop.ElapsedMilliseconds/1000 + " seconds. Please enter data manually.", "Solidworks Derped Error.");
}
return;
}//Still uses Macro (2-5-16)
public static void bbRun()
{
iSwApp.RunMacro2(macroPath + "BOUNDING_BOX.swp", "test11", "main", 0, out runMacroError);
return;
}
I was getting this same exact issue with SOLIDWORKS hanging on an open of a file. Almost all reference on SO was that you should never do this, but in this scenario, you either have to close it or wait forever. In C# I created a callWithTimeout method:
private void callWithTimeout(Action action, int timeoutMilliseconds, String errorText) {
Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action();
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds)) {
wrappedAction.EndInvoke(result);
} else {
threadToKill.Abort();
throw new TimeoutException(errorText);
}
}
Then the code that was hanging put in a block as such:
bool timedOut = false;
try {
callWithTimeout(delegate() {
// code that hangs here
}, 60000, "Operation timed out. SOLIDWORKS could not open the file. This file will be processed later.");
} catch (TimeoutException){
timedOut = true;
} finally {
if(timedOut) {
Process[] prs = Process.GetProcesses();
foreach (Process p in prs) {
if (p?.ProcessName.Equals("SLDWORKS") ?? false)
p?.Kill();
}
}
}

C# reinvoke current method

Not quite sure how to do this or if it even is a proper way to program c#. Maybe I need to rethink what I am trying to do, but I need some help.
I have a wpf application that starts/stops a service and also uses a named pipe to open a port and communicate with the service. So when the service needs to it can send a message to the app. I started a new thread to invoke a Wait() method that sits at namedPipeServerStream.WaitForConnection(). This works fine, but when the service is stopped I send a message to the app so it breaks the WaitForConnection, however I dont want to kill this thread, I want to reinvoke the same method and wait in a loop until the service starts again. Not sure of the best way to do this.
The code I have so far is below.
void Wait()
{
while (!ServiceControl.ServiceRunning)
{
Thread.Sleep(250);
if (exitProgram == true)
{
break;
}
}
while (ServiceControl.ServiceRunning)
{
try
{
NamedPipeServerStream namedPipeServerStream = new NamedPipeServerStream("pipeName");
namedPipeServerStream.WaitForConnection();
byte[] buffer = new byte[255];
namedPipeServerStream.Read(buffer, 0, 255);
string request = ASCIIEncoding.ASCII.GetString(buffer);
if (request != null)
{
if (request == "pipeExit")
{
Wait(); //Reinvoke Wait if svc calls to exit
}
else
{
//Do work on message
}
}
namedPipeServerStream.Close();
}
catch (Exception){}
}
if (_opener.exitProgram == true)
{
Application.Current.Dispatcher.InvokeShutdown();
}
Why don't you put a while(!opener.exitProgram) around your entire Wait implementation? That way you'll get back to the start once the pipe is closed.

TcpClient.EndConnect throws NullReferenceException when socket is closed

I am trying to connect to my server with a TcpClient.BeginConnect / TcpClient.EndConnect combo. However, some things don't work as they should.
The scenario is as follows:
Call to the TcpClient.BeginConnect
Server is intentionally offline (for testing purposes) - thus no connection can be made.
I close the application (client.Close() gets called in the process which closes the socket which in turn stops the async operation)
TcpClient connection callback method happens giving IAsyncResult
Call to the TcpClient.EndConnect method with the given IAsyncResult
NullReferenceException happens on EndConnect (?)
Since the last form (window) was closed, the app should exit - however it does not, at least not until BeginConnect operation completes (which is strange, as callback has already been called).
What happens here is that a NullReferenceException is caught. As you can see from the picture above, neither client nor ar are null. The problem is that the MSDN documentation for the EndConnect does not mention the case in which this exception is thrown.
So basically, I have no idea what is going on. The problem is that I am forced to wait for the app to close (as if the connection operation still waits for a timeout). If a server is online, it connects and disconnects just fine.
What does NullReferenceException in this context mean? How to avoid BeginConnect operation to block the application closing in case the connection can't be established?
Additional notes (requested in comments):
Here is the code to create the client (client is a member variable:
public void Connect()
{
try
{
lock (connectionAccess)
{
if (State.IsConnectable())
{
// Create a client
client = new TcpClient();
client.LingerState = new LingerOption(false, 0);
client.NoDelay = true;
State = CommunicationState.Connecting;
client.BeginConnect(address, port, onTcpClientConnectionEstablished, null);
}
else
{
// Ignore connecting request if a connection is in a state that is not connectable
}
}
}
catch
{
Close(true);
}
}
Also the Close method:
public void Close(bool causedByError)
{
lock (connectionAccess)
{
// Close the stream
if (clientStream != null)
clientStream.Close();
// Close the gateway
if (client != null)
client.Close();
// Empty the mailboxes
incomingMailbox.Clear();
outgoingMailbox.Clear();
State = causedByError ? CommunicationState.CommunicationError : CommunicationState.Disconnected;
}
}
The NullReferenceException is probably due to TcpClient.Client being null.
If you were to follow the MSDN Example for TcpClient.BeginConnect and pass theTcpClient object as the state object:
private void onConnEst(IAsyncResult ar)
{
try
{
TcpClient client = (TcpClient)ar.AsyncState;
if(client!=null && client.Client!=null)
{
client.EndConnect(ar);
}
}
catch(Exception ex){...}
}
This should handle the case when Close() is called before the Callback.
Going back to your problem - how long does it take for the application to eventually close?
This obviously a bug inside the TcpClient class. I have also faced it. TcpClient.Dispose may set Client field to null but EndConnect does not expect that.
I had a similar error and ended up using this code. I am not sure if it will hold with the IASyncResult interface, but there may be a similar way to run this check. I do notice that your ar.AsyncState == null, so perhaps try starting there, i.e. is it null when you connect properly?
private void connConnectCompleted(AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
// Something didn't work...abort captain
CloseSocket();
Console.WriteLine(this.GetType().ToString() + #":Error connecting socket:" + e.Error.Message);
return;
}
// Do stuff with your connection
}
EDIT: Sorry I didn't realise I didn't post what generated my AsyncCompletedEventArgs, which is more related to what you are doing. You will see the reason why I was wondering as to ar.AsyncState being null.
private void OnConnect(IAsyncResult asyncResult)
{
if (OnConnectCompleted == null) return; // Check whether something is using this wrapper
AsyncCompletedEventArgs args;
try
{
Socket outSocket = (Socket) asyncResult.AsyncState;
// Complete connection
outSocket.EndConnect(asyncResult);
args = new AsyncCompletedEventArgs(null);
OnConnectCompleted(this, args);
}
catch (Exception e)
{
args = new AsyncCompletedEventArgs(e.Message);
OnConnectCompleted(this, args);
}
}
This is a know bug.
You should be receiving 'ObjectDisposedException' instead of 'NullReferenceException'.

HttpWebRequest Limitations? Or bad implementation

I am trying to build a c# console app that will monitor about 3000 urls (Just need to know that HEAD request returned 200, not necessarily content, etc.)
My attempt here was to build a routine the checks the web URLS, looping and creating threads each executing the routine. What's happening is if i run with <20 threads, it executes ok most of the time, but if i use >20 threads, some of the url's time out. I tried increasing the Timeout to 30 seconds, same occurs. The network I am running this on is more than capable of executing 50 HTTP HEAD requests (10MBIT connection at ISP), and both the CPU and network run very low when executing the routine.
When a timeout occurs, i test the same IP on a browser and it works fine, I tested this repeatedly and there was never a case during testing that a "timed out" url was actually timing out.
The reason i want to run >20 threads is that i want to perform this test every 5 minutes, with some of the URL's taking a full 10sec (or higher if the timeout is set higher), i want to make sure that its able to run through all URLs within 2-3 minutes.
Is there a better way to go about checking if a URL is available, or, should I be looking at the system/network for an issue.
MAIN
while (rdr.Read())
{
Thread t = new Thread(new ParameterizedThreadStart(check_web));
t.Start(rdr[0]);
}
static void check_web(object weburl)
{
bool isok;
isok = ConnectionAvailable(weburl.ToString());
}
public static bool ConnectionAvailable(string strServer)
{
try
{
strServer = "http://" + strServer;
HttpWebRequest reqFP = (HttpWebRequest)HttpWebRequest.Create(strServer);
reqFP.Timeout = 10000;
reqFP.Method = "HEAD";
HttpWebResponse rspFP = (HttpWebResponse)reqFP.GetResponse();
if (HttpStatusCode.OK == rspFP.StatusCode)
{
Console.WriteLine(strServer + " - OK");
rspFP.Close();
return true;
}
else
{
Console.WriteLine(strServer + " Server returned error..");
rspFP.Close();
return false;
}
}
catch (WebException x)
{
if (x.ToString().Contains("timed out"))
{
Console.WriteLine(strServer + " - Timed out");
}
else
{
Console.WriteLine(x.Message.ToString());
}
return false;
}
}
Just remember, you asked.
Very bad implementation.
Do not go creating threads like that. It does very little good to have more threads than processor cores. The extra threads will pretty much just compete with each other, especially since they're all running the same code.
You need to implement using blocks. If you throw an exception (and chances are you will), then you will be leaking resources.
What is the purpose in returning a bool? Do you check it somewhere? In any case, your error and exception processing are a mess.
When you get a non-200 response, you don't display the error code.
You're comparing against the Message property to decide if it's a timeout. Microsoft should put a space between the "time" and "out" just to spite you.
When it's not a timeout, you display only the Message property, not the entire exception, and the Message property is already a string and doesn't need you to call ToString() on it.
Next Batch of Changes
This isn't finished, I don't think, but try this one:
public static void Main()
{
// Don't mind the interpretation. I needed an excuse to define "rdr"
using (var conn = new SqlConnection())
{
conn.Open();
using (var cmd = new SqlCommand("SELECT Url FROM UrlsToCheck", conn))
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// Use the thread pool. Please.
ThreadPool.QueueUserWorkItem(
delegate(object weburl)
{
// I invented a reason for you to return bool
if (!ConnectionAvailable(weburl.ToString()))
{
// Console would be getting pretty busy with all
// those threads
Debug.WriteLine(
String.Format(
"{0} was not available",
weburl));
}
},
rdr[0]);
}
}
}
}
}
public static bool ConnectionAvailable(string strServer)
{
try
{
strServer = "http://" + strServer;
var reqFp = (HttpWebRequest)WebRequest.Create(strServer);
reqFp.Timeout = 10000;
reqFp.Method = "HEAD";
// BTW, what's an "FP"?
using (var rspFp = (HttpWebResponse) reqFp.GetResponse()) // IDisposable
{
if (HttpStatusCode.OK == rspFp.StatusCode)
{
Debug.WriteLine(string.Format("{0} - OK", strServer));
return true; // Dispose called when using is exited
}
// Include the error because it's nice to know these things
Debug.WriteLine(String.Format(
"{0} Server returned error: {1}",
strServer, rspFp.StatusCode));
return false;
}
}
catch (WebException x)
{
// Don't tempt fate and don't let programs read human-readable messages
if (x.Status == WebExceptionStatus.Timeout)
{
Debug.WriteLine(string.Format("{0} - Timed out", strServer));
}
else
{
// The FULL exception, please
Debug.WriteLine(x.ToString());
}
return false;
}
}
Almost Done - Not Tested Late Night Code
public static void Main()
{
using (var conn = new SqlConnection())
{
conn.Open();
using (var cmd = new SqlCommand("", conn))
{
using (var rdr = cmd.ExecuteReader())
{
if (rdr == null)
{
return;
}
while (rdr.Read())
{
ThreadPool.QueueUserWorkItem(
CheckConnectionAvailable, rdr[0]);
}
}
}
}
}
private static void CheckConnectionAvailable(object weburl)
{
try
{
// If this works, it's a lot simpler
var strServer = new Uri("http://" + weburl);
using (var client = new WebClient())
{
client.UploadDataCompleted += ClientOnUploadDataCompleted;
client.UploadDataAsync(
strServer, "HEAD", new byte[] {}, strServer);
}
}
catch (WebException x)
{
Debug.WriteLine(x);
}
}
private static void ClientOnUploadDataCompleted(
object sender, UploadDataCompletedEventArgs args)
{
if (args.Error == null)
{
Debug.WriteLine(string.Format("{0} - OK", args.UserState));
}
else
{
Debug.WriteLine(string.Format("{0} - Error", args.Error));
}
}
Use ThreadPool class. Don't spawn hundreds of threads like this. Threads have such a huge overhead and what happens in your case is that your CPU will spend 99% time on context switching and 1% doing real work.
Don't use threads.
Asynch Call backs and queues. Why create a thread when the resource that they are all wanting is access to the outside world. Limit your threads to about 5, and then implement a class that uses a queue. split the code into two parts, the fetch and the process. One controls the flow of data while the other controls access to the outside world.
Use whatever language you like but you won't got wrong if you think that threads are for processing and number crunching and async call backs are for resource management.

Program hangs, waiting for input that I can never give

I'm using visual studio to program this small TcpServer.
It's really specific. The server listens to port 1234 and is located on IP 127.0.0.1
Our teachers gave us a program that tries to connect to that port on that IP when you click "connect". It's working for everyone else, so it must be a coding error on my part.
When I click connect, the program sends the word "GET" over the stream, to which I have to respons with a list of allready connected IP-adress and then a newline containing only a .
When I disconnect, the program sends the word "REM" and I simply have to remove if from my list(which is a generic list)
I have a class TCPServer(we had to make our own), which has this as main code:
this.tl = new TcpListener(IPAddress.Any, PORT);
tl.Start();
while(true)
{
TcpClient tcl = tl.AcceptTcpClient();//here the server will wait forever untill someone connects, meaning the "new Thread" statement is never reached untill someone connects.
TcpHelper th = new TcpHelper(tcl,conf);
new Thread(new ThreadStart(th.Start)).Start();//should be multi-threaded, not sure if it is.
//t.Start();
}
TcpHelper looks like this(look for the commented text "here's the problem" within the usings):
public class TcpHelper
{
private TcpClient tc;
private IPEndPoint ipe;
private string get;
private Configuration conf;
public TcpHelper(TcpClient tc, Configuration conf)
{
this.tc = tc;
this.conf = conf;
}
public void Start()
{
using (NetworkStream nws = this.tc.GetStream())
{
using (StreamReader sr = new StreamReader(nws))
{
using (StreamWriter sw = new StreamWriter(nws))
{
this.ipe = (IPEndPoint)tc.Client.RemoteEndPoint;
this.conf.List.Add(this.ipe.Address);
bool conn = true;
while (conn)
{
this.get = sr.ReadLine();//here's the problem
switch (this.get)
{
case "GET":
foreach (IPAddress address in this.conf.Lijst)
{
sw.WriteLine(address.ToString());
}
sw.WriteLine(".");
break;
case "REM":
this.conf.List.Remove(this.ipe.Address);
sw.WriteLine("OK.");
conn = false;
break;
default:
break;
}
}
}
}
}
}
#region Properties
public IPEndPoint Ipe
{
get
{
return this.ipe;
}
}
#endregion
}
My guess is that your problem is that you're calling sr.ReadLine(), but the input does not contain a newline, so it's blocked there waiting for a newline that will never come.
you may want to try calling StreamReader.Read 3 times to build up the command string (GET/REM) before you act on it. (Note: 3 times is because all commands are three characters).
Read will return integers, but after checking that they are not -1 (indicating end-of-file), you can cast that integer to a char.
Sorry, maybe I'm not understanding this... Did you write this code?
this.tl = new TcpListener(IPAddress.Any, PORT);
tl.Start();
while(true)
{
TcpClient tcl = tl.AcceptTcpClient();
TcpHelper th = new TcpHelper(tcl,conf);
new Thread(new ThreadStart(th.Start)).Start();
//t.Start();
}
This is going to blow the **** out of any computer. You're looping infinitely, creating new threads on each loop. So, if you create one new thread per loop, and each loop takes one millisecond (lets say its very slow!), in five seconds you've got 5,000 threads. Each trying to listen at the same port.
Try using a single thread. If this is a console app, use Console.ReadLine() to block the main thread until somebody presses the enter key.
With the new information... AcceptTcpClient blocks, but instead of creating a new thread the work should be queued on the ThreadPool.

Categories