Okay well, here is the code:
private void Receivev2()
{
try
{
using (UdpClient udpclient = new UdpClient(1500))
{
while (connect == true)
{
byte[] byteData = udpclient.Receive(ref remoteEP);
waveProvider.AddSamples(byteData, 0, byteData.Length);
if (Record == true)
{
waveWriter.Write(byteData, 0, byteData.Length);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "VoiceChat-Receive ()", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
It´s on a Thread, and well, it receives data from udp and plays it, nothing weird.
My problem however, is to make it stop normally, or well, don´t know how to put it.
But let´s say, i start the thread and it loops.
Then if i close my application, the application won´t "close", as the thread isn´t closing.
Now to solve that, i use IsBackground = true.
But i am not sure if that is an optimal way to do it, it feels like it will just force it to shut down, like ProcessKill or something.
Maybe it is the correct way, i don´t know.
Please give me advice on this.
The trick is call UdpClient.Close. This will cancel any pending operations and "poke" the Receive method into throwing a SocketException if it is blocking. Obviously, you will have to call Close from another thread which means you will need to refactor your code a bit so that udpclient is no longer a local variable. You will also need to set connect to false so that the loop ends.
So to summarize the steps are as follows.
Call Close to prevent Receive from blocking.
Set connect to false.
Refactor your code to make the above possible.
If it's a import thread, you'd better not set IsBackground , because the main thread stop,It will be forced stop
stop thread step:
1 set connect=false ,than main thread sleep a while untill it stop
2 if the thread still alive, you can abort it ,this step is not necessary
3 than join the back thread to main thread
just like this:
connect= false;
Thread.Sleep(200);
if (thread1 != null)
{
if (thread1 .IsAlive)
{
thread1 .Abort();
thread1 .Join();
}
}
Related
When setting up my socket for connecting, I wrap the method in a try-catch block..
If a socket exception gets raised, I create a new thread.. sleep for 15 seconds.. and then call the connect method again but this time from another thread. I'm doing this mainly for the sleep method (to avoid using a timer to reconnect) to not hang up the main thread.
Anyhow.. when trying to connect, I write the status to a text box using a method called Write() which just appends the text to the current text with a \n before it...
Because on a failed connect I create a separate thread to call the connect method (which DOES modify a control on the form), I am right to use invoke on the method call right?
Here is my code
private void Connect()
{
try
{
Write("Connecting...");
_ClientSocket.Connect(new IPEndPoint(IPAddress.Loopback, 2500));
Connected = true;
Write("Connected.");
_ClientSocket.BeginReceive(Buffer, 0, Buffer.Length, 0, new AsyncCallback(RecieveCallBack), null);
}
catch (SocketException ex)
{
Write("Connection Failed. Trying again in 15 Seconds...");
Connected = false;
new Thread(delegate()
{
Thread.Sleep(15000);
Invoke((MethodInvoker)delegate
{
this.Connect();
});
}).Start();
}
catch (Exception ex)
{
}
}
I just want to be sure I am doing this in the proper way
Instead of creating thread to connect you could initially assume, what your connect will not be successful. This will required to have polling timer to reconnect. Bonuses: you can control timer (while you can do nothing with anonymous thread), you can use it for other tasks required polling (resend data, which was not delivered at first try, queue connect after disconnect if you change socket settings, etc).
This polling timer can be a normal UI timer (Timer in case of winforms), then you don't need any invoke. If you go this way, then make sure don't have blocking operations in it (to example, sending data and waiting for an answer).
Otherwise, you can use this extension method for methods to always run them in UI thread
public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
if (control.InvokeRequired)
control.Invoke(action);
else
action();
}
In your case you will want to call Write like this
someUIControl.InvokeIfRequired(() => Write(...));
Or simply make Write method like this
void Write(...)
{
if(someUIControl.InvokeRequired)
someUIControl.Invoke((delegate)() => Write(...));
else
{
... job here
}
}
In the scenario presented, it is using new Thread, Thread.Sleep and Invoke simply as a way of schedule some work to happen on the UI thread in 15 seconds. It'll work, but... pretty inefficient (threads are expensive). Frankly, a timer should be used instead - or perhaps Task.Delay on 4.5 (which actually just wraps a timer anyway).
I have a connection with an IRC server over TCP. I read the data with an independent task, so far, so good. However, if I want to quit the program, I can't quit the thread because it is stuck in the reader.ReadLine() command (threadShouldRun has no impact). Using Interrupt() or Abort() doesn't appear to change anything either.
Either I need a way to determine when there are more lines to read, or I need to forcefully kill the thread (even though that's bad).
private System.Threading.Thread myThread;
private bool threadShouldRun = true;
private StreamReader reader;
private void readStream()
{
while(threadShouldRun)
{
string line = reader.ReadLine();
if (line != null)
{
newLineEvent(this, new NewLineEventArgs(line));
}
}
}
Use asynchronous calls like BeginRead as shown here and avoid the loop:
http://msdn.microsoft.com/en-us/library/system.io.stream.beginread.aspx
A solution would be to set a TimeOut on your receiving socket ( http://msdn.microsoft.com/it-it/library/system.net.sockets.socket.receivetimeout(v=vs.110).aspx ).
Once the time expires, a SocketException will be raised, so you can catch it and reiterate the control on your threadShouldRun.
In case you want to quit (and hence set threadShouldRun to false), there are two scenarios:
Data received, you will handle it, and on the next check the variable will be found false and thread will terminate;
No Data received, TimeOut happens, Exception is raised, you will handle it, and on the check the thread will terminate.
I'm coding singleton class that runs a background thread. Here is how it started and maintained:
private void EnsureBackgroundThread()
{
try
{
if (this.RunnerThread == null)
this.RunnerThread = new Thread(this.BackgroundRunner) { IsBackground = true };
if (this.RunnerThread.ThreadState != ThreadState.Running)
{
Debug.WriteLine("----ApplePushNotificatorService.EnsureBackgroundThread ThreadState: " + this.RunnerThread.ThreadState);
this.RunnerThread.Start();
}
}
catch (Exception ex)
{
this.LoggerService.Log(null, ex);
}
}
I call my method in this class from TestClass like so:
apns.Send("dev", devices, "Testing...", out badIds);
// Wait 5 seconds to let it send stuff through.
Thread.Sleep(5000);
devices.Clear();
devices.Add("some bad id");
// Now let's call this again, but this time we should get back some bad Ids
apns.Send("dev", devices, "Testing...", out badIds);
// Wait 5 seconds to let it send stuff through.
Thread.Sleep(5000);
devices.Clear();
devices.Add("9edc21d0d4e369f50040c5d2c94f2ea29c7d596090e4ddae253712cd406391df");
apns.Send("dev", devices, "Test message for Andrew's phone", out badIds);
// Wait 5 seconds to let it send stuff through.
Thread.Sleep(5000);
I checked error logs and I see exceptions:
Thread is running or terminated; it cannot restart.
In debug it says:
----ApplePushNotificatorService.EnsureBackgroundThread ThreadState: Background, WaitSleepJoin
Why does it enter "WaitSleepJoin" state? Is it because I do "Thread.Sleep" in my test?
Does my code to keep thread alive look correct? How do I work around this? The idea is when "Send" method called on singleton - we need to make sure background thread is running.
EDIT:
This is re-worked code that is working properly
private void EnsureBackgroundThread()
{
try
{
if (this.RunnerThread != null && this.RunnerThread.IsAlive) return;
this.RunnerThread = new Thread(this.BackgroundRunner) { IsBackground = true };
this.RunnerThread.Start();
}
catch (Exception ex)
{
this.LoggerService.Log(null, ex);
}
}
The state tells us that the thread is currently sleeping, likely in one of your calls to Sleep. This means it's still running. Because it's still running, you cannot start it. You're trying to start the same thread multiple times. You can't do that. You start it once, then it's started, and that's that. Trying to start it a second time, either while it's running, or after it is done, is not possible.
Quite simply, as the error states: your thread has been created and is running or terminated - and then you try to start it again.
Presumably in your TestClass you have multiple calls to your singleton class (I'm guessing this may be somewhere under the apns.Send call). The first time you call EnsureBackgroundThread, a single thread will be created and started. The next time you call EnsureBackgroundThread will call Thread.Start on the same thread, thus causing the same error.
It's perhaps important to note here that, when a thread completes, the variable referencing it isn't set to null - but more likely you're just calling the EnsureBackgroundThread method more than once and the code you've written doesn't support that.
I'm designing a small program whose objective is to make sure one of our server is up and running. In some cases, the server won't answer and a script must be launched to restart the server.
First I'm starting a new thread responsible of fetching the information, which is then joined by the main thread for a certain time span. I then abort the thread to disconnect and finally join it to leave enough time to execute the catch and finally blocks.
In theory it should work great : if the time span is short enough, it indeed indicates that the server is down (because no connection could be made in the short allocated timespan). But in certain cases, when the server is really down, the program will just keep executing, as if the ThreadAbortException had no effect. Problem is, these downtimes are quite sporadic so I couldn't debug it myself to see what was not working properly.
Here's how it goes :
This here is the main thread, calling the worker thread. Very straightforward.
public void LaunchCommand()
{
Thread pingThread = new Thread(new ThreadStart(Ping));
pingThread.Start();
while (!pingThread.IsAlive);
pingThread.Join(new TimeSpan(0, 0, _maxTime));
pingThread.Abort(); // Time's up.
pingThread.Join(); // Make sure we complete everything before moving on
}
And here's the called thread :
private void Ping()
{
try
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
serviceType = Type.GetTypeFromProgID(serviceProgID, _server, true);
service = Activator.CreateInstance(serviceType);
_xmlResult = ApxServiceType.InvokeMember("ExecuteXML", BindingFlags.InvokeMethod, null, service, new string[] { _dataset, Command, string.Empty }) as string;
stopwatch.Stop();
_latency = stopwatch.Elapsed;
// Trivial validations to make sure _status is true, such as _xmlResult.Contains(certainSubString); and such
_status = true; // Everything seems to work fine if we could make up to here.
}
catch (ThreadAbortException)
{
Console.WriteLine("Server timeout :(");
return;
}
catch (Exception e)
{
Console.WriteLine("Server exception: " + e.Message);
return;
}
finally
{
if (!_status)
{
_latency = new TimeSpan(0, 0, _maxTime);
}
}
}
Variables such as Commands, serviceProgID, etc. have been declared elsewhere and are known to work well. I guess my problem spans from the three lines following the stopwatch declaration/initialization. First, I must say I copy pasted these lines from a similar application, but basically it should only fetch a result from the given Command. Unfortunately, because I couldn't debug under the critical situation, I don't which line is problematic, but anyway, it seems the ThreadAbortException has no effect. Is it because code has been switched off to unmanaged?
I'm lost here so any idea would be welcomed! Thanks!
I actually don't see a need to use a separate thread for your scenario. You may check for server availability using synchronous operation. Does the function being used to check server availability offer timeout option? If yes then the timeout option should be enough. If the function returns before the timeout then it means server is online otherwise server is down.
If the function for checking server availability does not offer timeout option and may cause the thread to wait forever (or for a long time) then you may use a new thread. However if Thread.Join(Timeout) method returns true and _status variable is also true then you can be certain that the server is online. If Thread.Join(Timeout) returns false then it would mean that the server is down.
As a good practice, you should use Thread.ResetAbort in the catch block handling Abort exception. Otherwise runtime will rethrow the ThreadAbort exception once catch block finishes execution.
I've got a little problem with ending the work of one of my threads. First things first so here's the app "layout":
Thread 1 - worker thread (C++/CLI) - runs and terminates as expected
for(...)
{
try
{
if(TabuStop) return;
System::Threading::Monitor::Enter("Lock1");
//some work, unmanaged code
}
finally
{
if(stop)
{
System::Threading::Monitor::Pulse("Lock1");
}
else
{
System::Threading::Monitor::Pulse("Lock1");
System::Threading::Monitor::Wait("Lock1");
}
}
}
Thread 2 - display results thread (C#)
while (WorkerThread.IsAlive)
{
lock ("Lock1")
{
if (TabuEngine.TabuStop)
{
Monitor.Pulse("Lock1");
}
else
{
Dispatcher.BeginInvoke(RefreshAction);
Monitor.Pulse("Lock1");
Monitor.Wait("Lock1", 5000);
}
}
// Thread.Sleep(5000);
}
I'm trying to shut the whole thing down from app main thread like this:
TabuEngine.TabuStop = true; //terminates nicely the worker thread and
if (DisplayThread.IsAlive)
{
DisplayThread.Abort();
}
I also tried using DisplayThread.Interrupt, but it always blocks on Monitor.Wait("Lock1", 5000); and I can't get rid of it. What is wrong here? How am I supposed to perform the synchronization and let it do the work that it is supposed to do?
//edit
I'm not even sure now if the trick with using "Lock1" string is really working and locks are placed on the same object..
A nice example of producer / consumer synchronization using Monitors you can find on MSDN (Example 2).
There are two threads (producer and consumer, similar like in your case), but synchronization is done by introducing third class which locks shared resources. Example provides full source code, so I didn't post it here.
These are monitors, not auto reset or manual reset events. You need a condition to check to properly use wait. Otherwise, if you Pulse before you start waiting you will miss the the Pulse. Generally the pattern looks like:
Thread A:
lock(x)
{
... work ....
while(!some_condition)
Monitor.Wait(x)
}
Thread B:
lock(x)
{
... other work ...
some_condition = true;
Monitor.Pulse(x)
}
By manipulating and checking some_condition with the lock held, we ensure that that no matter when the pulse happens (either before we start waiting in A or afterwards) A can always react appropriately and not wait forever for a pulse that already came.