I have a class (NamedPipeManager) which has a thread (PipeThread) that waits for a NamedPipe connection using (ConnectNamedPipe) and then reads (ReadFile) - these are blocking calls (not-overlapped) - however there comes a point when I want to unblock them - for example when the calling class tries to stop the NamedPipeManager...
How can I interupt it? Using Thread.abort? Thread.interrupt? Is there a proper way to handle this?
Refer to the code below which illustrates my current situation
main()
{
NamedPipeManager np = new NamedPipeManager();
... do stuff ...
... do stuff ...
np.Stop(); // at this point I want to stop waiting on a connection
}
class NamedPipeManager
{
private Thread PipeThread;
public NamedPipeManager
{
PipeThread = new Thread(new ThreadStart(ManagePipes));
PipeThread.IsBackground = true;
PipeThread.Name = "NamedPipe Manager";
PipeThread.Start();
}
private void ManagePipes()
{
handle = CreateNamedPipe(..., PIPE_WAIT, ...);
ConnectNamedPipe(handle, null); // this is the BLOCKING call waiting for client connection
ReadFile(....); // this is the BLOCKING call to readfile after a connection has been established
}
public void Stop()
{
/// This is where I need to do my magic
/// But somehow I need to stop PipeThread
PipeThread.abort(); //?? my gut tells me this is bad
}
};
So, in function Stop() - how would I gracefully unblock the call to ConnectNamedPipe(...) or ReadFile(...)?
Any help would be appreciated.
Thanks,
It seems to be working on VC6.0, WinXP if I try to interrupt ConnectNamedPipe by
DeleteFile("\\\\.\\pipe\\yourpipehere");
So just specify name, not handle.
Starting with Windows Vista, there is a CancelSynchronousIO operation available for threads. I don't think there is a C# wrapper for it, so you would need to use PInvoke to call it.
Before Vista, there isn't really a way to perform such an operation gracefully. I would advise against using thread cancellation (which might work, but doesn't qualify as graceful). Your best approach is to use overlapped IO.
Recently I was in a situation, I could not use the Async Overlapped IO. I was stuck on the server side within ConnectNamedPipe. To unlock the thread and free resources, I had to connect to the same pipe as a client for a split second.
Main thread receives the stop signal
Main thread sets the stop event for the listening thread
Main thread connects to the pipe
If succeeded (always) - closes the newly created handle immediately
Listener thread unlocks
Listener thread does whatever required
This worked for me very well.
To unblock ReadFile one needs to connect and write to the pipe. Same effect epected.
Related
I am just learning about Threads in C# and a question arose.
I have a TCP-Server-Class which accepts connections and passes them to a TCP-Client-Class.
The code roughly looks like this: (dummy code)
Class TcpServer
{
public static Main(string[] args)
{
while(true)
{
//I create a new instance of my "TCP-Client-Class" and pass the accepted connection to the constructor
ConnectionHandler client = new ConnectionHandler(TCPListner.acceptconnections);
//create a new Thread to handle that connection
Thread client1 = new Thread (client.handleConnection()); //and start handling it
client.start;
//Do some other stuff for protokolling
do.someOtherStuff;
// and then wait for a new connection
}
}
//Some other Methods etc.
}
Class ConnectionHandler
{
//Constructor in which a connection TCPclient connection has to be passed
public ConnectionHandler(TCPclient client)
{
//Do stuff
}
//Method to handle connection
public void handleConnections()
{
//Open streams
//.
//.
//.
//close streams
//close connections
}
}
Now to my questions:
a) Is it obligatory to close that Thread again, after it reached the "close connection" part?
b) To close a thread do I just have to call the .join Method in my main class or is there anything else I have to take care about.
c) Incase of an error, can I just simply leave the "handleConnection()" method and close that thread (ofc with appropriate error-handling)?
d) Is it important to drop the "client" reference or the "client1" reference? Or is it just consumed by the garbage collector?
Well, it's entirely fine to let the thread just complete normally. If the top-level call of a thread throws an exception, it may take down the process, depending on how the CLR is configured. It's usually better to have a top-level error handler to log the error and move on.
However, you should consider what you want to happen on shutdown:
Your while (true) loop should be changed to allow some mechanism for shutting down
If you keep track of all the threads currently handling existing requests, when you know you're trying to shut down, you can Join on them (probably with a timeout) to allow them to complete before the server finishes. However, you want to remove a thread from that collection when it completes. This sort of thing gets fiddly fairly quickly, but is definitely doable.
As an aside, it's more common to use a thread-pool for this sort of thing, rather than creating a brand new thread for each request.
I have a synchronous task but sometime thread get stuck while making a remoting call which blocks the execution. So I want to make remote call making part async using a ThreadPool thread , but my idea is to keep it synchronous as much possible, that is I want main thread to wait for a timout value or ThreadPool thread to complete ,so that this activity is asynchronous only in case of thread stuck.
ThreadPool thread doesn't give any handle so that I can call thread.join(timeout) on that and I can't use autoreset events also as that part of code can be accessed by multiple threads so which thread sets / resets autoreset event becomes even complicated and also it is an overhead.
Can you please suggest a cleaner way for this problem ?
I can't create Thread also using Thread class because as I mentioned above that area of code can be accessed by multiple threads and it is a small task that remote call does ,something like updating a text like progress .
Code Snippet:
public static Exception AddProgress(Session session, ITaskSetProgress progress)
{
IIconUIServer server = IconRemotingServer.Instance.GetUiServer(session);//gets remote proxy object
server.AddProgress(progress);// calls a method over remoting IPC channel
}
And this method can be called by more than one thread at a time.
My intention is to write AppProgressAsync method ,so that when call server.AddProgress(progress); hangs then only it should behave as async ,so I have a timeout .
I can't use Task Library as I need to support old customers who are on .net 3.5 still.
I solved this issue by using async delegates :something like below:
public static void AddProgressAsync(Session session, ITaskSetProgress progress)
{
AddProgressDelegate addProgress = new AddProgressDelegate(AddProgress);
try
{
IAsyncResult result = addProgress.BeginInvoke(session, progress, null, null);
result.AsyncWaitHandle.WaitOne(timeoutValue);
}
catch (Exception ex)
{
}
finally
{
addProgress = null;
}
}
public static void AddProgress(Session session, ITaskSetProgress progress)
{
IIconUIServer server = IconRemotingServer.Instance.GetUiServer(session);//gets remote proxy object
server.AddProgress(progress);// calls a method over remoting IPC channel
}
It works fine in this scenario !!
I'm wanting to make sure that when my application quits that any and all open threads are closed. However when I try to do so I get the error telling me that there is no reference object for what I'm trying to do, even though it's all in the same class.
Can someone please help me out?
Starting / opening threads:
Thread listen_thread;
TcpListener tcp_listener;
Thread clientThread;
// Use this for initialization
void Start ()
{
IPAddress ip_addy = IPAddress.Parse(ip_address);
tcp_listener = new TcpListener(ip_addy, port);
listen_thread = new Thread(new ThreadStart(ListenForClients));
listen_thread.Start();
Debug.Log("start thread");
}
Then my attempt at closing them:
void OnApplicationQuit()
{
try
{
clientThread.Abort();
tcp_listener.Stop();
listen_thread.Abort();
}
catch(Exception e)
{
Debug.Log(e.Message);
}
}
What am I doing wrong? The threads open and do what they are suppose to just fine, but for some reason I can't close them.
You shouldn't force a thread to Abort, there is a lot of good answers on SO and web elsewhere on this topic, e.g:
Put the thread in its own process. When you want it to stop, kill the process.
How To Stop a Thread in .NET (and Why Thread.Abort is Evil)
You don't need to cancel the thread.
msdn on THread.Abort(). See remarks section.
Instead you should implement a cancalation pattern, for example via Task or BackgroundWorker classes. In this case you basically say: "stop or break whatever you doing and just exit the method". You can also roll out your own implementation: query a volatile bool or using event handles, but probably stick to the solutions already available. More info in this answer.
I spent some time searching for an answer to this and found plenty of helpful information in other threads. I believe I've written the code in a way that works, but I am not happy with the outcome.
I designed a piece of hardware that I am communicating with via C#. The hardware connects via USB and runs initialization routines after enumerating with the OS. At that point, it simply waits for the C# program to start sending commands. In my C# code, the user must press a "Connect" button, which sends a command and the required payload to let the hardware know it should continue running. The hardware then sends a command back as an ACK. The problem is that my C# program must wait to receive the ACK, but the GUI is totally frozen until the hardware responds as I don't know how to partition it out to another thread that can block freely. If the hardware responds immediately, then it works fine, but if it can't connect, then the program stays frozen indefinitely.
With that said, I know a few things need to happen, but I'm not sure how to implement them. First and foremost, I don't think sitting in a loop waiting on a boolean is the right way to go, but using AutoResetEvent doesn't really seem to be much better. There has to be a better way involving timers, more threads, or something similar.
I am using the DataReceived event with the serialPort object as follows:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
byte cmd = (byte)serialPort1.ReadByte();
if (cmd == (byte)Commands.USB_UART_CMD_MCU_CONNECT)
MCU_Connect_Received.Set();
}
In the buttonClick function ("main" thread), the program stops while it waits for the ACK:
//Send the command to signal a connection
Send_Connection_Packet((byte)Commands.USB_UART_CMD_PC_CONNECT);
textBox1.AppendText("-I- Attempting to contact hardware...");
MCU_Connect_Received.WaitOne();
textBox1.AppendText("Success!" + Environment.NewLine);
Ideally, I'd like to know if a timeout expired so I can print "Failed!" instead of "Success!". Not having a timeout also means it will sit there forever, as I mentioned above, until I kill the process. It's possible that it won't find any hardware, but if it does, it should respond in < 1 second, so a timeout of 2 seconds would be more than enough. I tried using Thread.Sleep, but that froze the GUI as well.
I recommend you use the Task class. You can use a TaskCompletionSource to complete the task when the operation completes.
Using the new async support, your code then becomes:
textBox1.AppendText("-I- Attempting to contact hardware...");
await Send_Connection_Packet((byte)Commands.USB_UART_CMD_PC_CONNECT);
textBox1.AppendText("Success!" + Environment.NewLine);
If you don't want to use the Async CTP, then you can call Task.ContinueWith and pass TaskScheduler.FromCurrentSynchronizationContext to schedule the textBox1.AppendText("Success!") line to run on the UI thread.
The async support also includes timers (TaskEx.Delay) and combinators (TaskEx.WhenAny), so you can easily check for timeouts:
textBox1.AppendText("-I- Attempting to contact hardware...");
var commTask = Send_Connection_Packet((byte)Commands.USB_UART_CMD_PC_CONNECT);
var timeoutTask = TaskEx.Delay(1000);
var completedTask = TaskEx.WhenAny(commTask, timeoutTask);
if (completedTask == commTask)
textBox1.AppendText("Success!" + Environment.NewLine);
else
textBox1.AppendText("Timeout :(" + Environment.NewLine);
The issue with the GUI freezing is because all the callbacks for GUI events occur in the thread that's running the GUI. If you don't want the GUI to freeze you need to spawn a new thread.
For implementing the timeout, you can do a timed wait on an event handle and then check the return value for true or false to determine if the call was successful or if it timed out.
To enable timeouts use another overload of WaitOne():
bool succeeded = MCU_Connect_Received.WaitOne(timeOutInMilliseconds, false);
if (succeeded)
{
textBox1.AppendText("Success!" + Environment.NewLine);
}
else
{
textBox1.AppendText("Failed!" + Environment.NewLine);
}
Consider moving communication-related code in a separate class to encapsulate the communication protocol. This way the code will be easier to maintain and you will able to implement all Task/background worker ideas the other people suggested.
If you want the GUI to remain responsive, you should run things in a background thread. A BackgroundWorker does this nicely. I'd stick with the resetevent over a busy wait construction. You can use a timer to trigger the resetevent after a timeout period
I am currently using a third party component to handle telnet connections in .NET. I want it to be synchronous where I send a command to the receiving telnet server and then I get the response back as text or byte array. Only problem is that the component is not set up to do that. The component allows me to send commands to the server, but the response is returned via a function handle. So in essence, I need a way to pause the application while the handler does it's processing. Here is an example of how I plan to get around that issue:
static void Main(string[] args)
{
Telnet telCon = new Telnet();
telCon.OnDataIn += new Telnet.OnDataInHandler(HandleDataIn);
telCon.Connect(remoteHostStr);
while (true) ;
}
public static void HandleDataIn(object sender, TelnetDataInEventArgs e)
{
string responseStr = e.Text;
if (responseStr.Contains("Username:"))
{
((Telnet)sender).Send(System.Text.ASCIIEncoding.ASCII.GetBytes(username));
}
else if (responseStr.Contains("Password:"))
{
((Telnet)sender).Send(System.Text.ASCIIEncoding.ASCII.GetBytes(password));
}
}
The solution above will not work since the while will always run, but I will probably build a future version that uses some sort of global variable to track if the loop still needs to run. However, everything I have been taught about programming says this is very dirty. Can anyone think of another way around my dilemma?
Thanks,
Chris
Here is an example of using a ManualResetEvent to suspend execution (and delay program end) until your event handler says it's finished.
static ManualResetEvent finishGate;
static void Main(string[] args)
{
finishGate = new ManualResetEvent(false); // initial state unsignaled
Telnet telCon = new Telnet();
telCon.OnDataIn += new Telnet.OnDataInHandler(HandleDataIn);
telCon.Connect(remoteHostStr);
finishGate.WaitOne(); // waits until the gate is signaled
}
public static void HandleDataIn(object sender, TelnetDataInEventArgs e)
{
// handle event
if (processingComplete)
finishGate.Set(); // signals the gate
}
The WaitOne() method of ManualResetEvent also includes overrides that accept a timespan or number of milliseconds. It returns bool - true if it was signaled, false if it timed out. If you put that in a loop, you could have your main thread wake up every 30 seconds and perform some housekeeping tasks, but still have an instantaneous response when the gate is signaled.
Your while loop:
while(true) ;
will drive CPU usage to 100% (well, 100% of 1 core on a multicore machine) and leave it there, permanently.
This will starve other processes of CPU power, and may prevent the Telnet component from working at all because you've bypassed the message pump.
There are better ways, but without more information on what you're doing, it will be hard to advise you.
To begin, do you want a WindowsForms/WPF/Console application?
[And please, use comments to answer, not Answers.]
In general, when you really need to wait, use a WaitHandle. In this case, a ManualResetEvent would probably be what you need.
A better way would be to spawn the Telnet processing to another thread. That way you can get the main thread to wait for the telnet processing to complete.
Have a look here for some very good tutorials on threading.