I have a looper thread that is running always and pull tasks from queue in order to execute them.
There is a main looper method
public void Start()
{
m_looperThread = new Thread(() =>
{
while (true)
{
//Dequeue use lock inside
TASK_TYPE task = m_taskList.GetAndRemoveFirst();
if (task == null || !m_isThreadRunning)
{
break;
}
task.Execute();
FinishedTask(task);
}
}
)
{
IsBackground = true
};
m_looperThread.Start();
}
Now if I need to close an application, user need to click red cross and before closing I need to abort all looper tasks.
How I do it
public void Abort()
{
Put(default(TASK_TYPE));
m_isThreadRunning = false;
if (m_looperThread != null)
{
m_looperThread.Join();
}
m_taskList.Clear();
}
So, first of all I put a null item and additional I set m_isThreadRunning value to false because in looper method I am checking this values in order to stop it. Then I call .Join() to make sure that I finished this thread and clear task list. Now I know exactly that all tasks were aborted, threads were joined and all is fine.
But issue here in this line
task.Execute();
What is the issue - when task run and user need to close the application I can't .Join the looper thread before task finish the job (it could be 1 minute). And finally it is looks like application in stuck.
So, question is - how correctly .join the thread and give to user opportunity to close the application?
Related
Creating An MVVM application where application wants to connect to server on a button click. After clicking the button, a thread will be created to connect to the server so that UI doesn't freeze and terminates(TIME OUT is 15 secs). Next time click on the button is creating again new thread to connect to server and terminates.
But first time I want to create a new thread and later I want to reuse that thread(not new) to do the "connect" task if application is not closed and user clicked on the same button.
Is that possible?
Below is the code:
Class ConnectViewModel:BaseViewModel
{
public void ConnectToServer()
{
ConnectButtonEnable = false;
ConnectingServerText = Properties.Resources.TryingToConnectServer;
Thread thread = new Thread(new ThreadStart(connect));
thread.Start();
thread.Join();
}
public void connect()
{
bool bReturn = false;
UInt32 iCommunicationServer;
bReturn = NativeMethods.CommunicateServer(out iCommunicationServer);
if (!bReturn || NativeMethods.ERROR_SUCCESS != iCommunicationServer)
{
ConnectingServerText = Properties.Resources.UnableToConnectToServer;
}
else if (NativeMethods.ERROR_SUCCESS == iCommunicationServer)
{
ConnectingServerText = properties.Resources.SuccessfullyConnectedServer;
}
ConnectButtonEnable = true;
return;
}
}
Due to how the question is phrased I would recommend you to read up on MVVM and async patterns, some examples:
http://msdn.microsoft.com/en-us/magazine/dn605875.aspx
http://richnewman.wordpress.com/2012/12/03/tutorial-asynchronous-programming-async-and-await-for-beginners/
But in general, use async, don't manually create new threads when coding in a GUI-application. If the task shouldn't be callable whilst "running", do test and set via Interlocked.CompareExchange and store away some state.
You use threads for parallel work, not for "waiting on the network".
You can use the TPL to achieve this.
private Task previous = Task.FromResult(true);
public Task Foo()
{
previous = previous.ContinueWith(t =>
{
DoStuff();
});
return previous;
}
By having the operation schedule each operation as the continuation of the previous operation, you ensure that each one doesn't start until the one that came before it finished, while still running all of them in background threads.
Dont worry about creating and managing threads, just use ThreadPool.QueueUserWorkItem instead - its very efficient.
I have a WPF application in which i have this class :
public partial class Global : UserControl
{
public static List<Thread> listofthreads = new List<Thread>();
public Global()
{
InitializeComponent();
Thread windowThread = new Thread(delegate() { verifing(); });
listofthreads.Add(windowThread);
windowThread.Start();
}
public void verifing()
{
if (Global2.Pat_pathregfile.Length > 5 && Global2.Pat_pathcalibfile.Length > 5) {
if (utilisation.Dispatcher.CheckAccess())
{
utilisation.Visibility = Visibility.Visible;
}
else
{
utilisation.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
utilisation.Visibility = Visibility.Visible;
}));
}
foreach (Thread t in listofthreads) {
try
{
t.Suspend();
}
catch { }
}
}
else {
if (utilisation.Dispatcher.CheckAccess())
{
utilisation.Visibility = Visibility.Hidden;
}
else
{
utilisation.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
utilisation.Visibility = Visibility.Hidden;
}));
}
Thread windowThread = new Thread(delegate() { verifing(); });
windowThread.Start();
listofthreads.Add(windowThread);
}
}
}
i need to kill properly all of the threads that i have used
foreach (Thread t in listofthreads) {
try
{
t.Suspend();
}
catch { }
}
But the program indicates that the use of the method suspend isn't recommended .
Why?
It seems that some threads is still working even after the close of the windows, Why this happens? How can i fix it?
Is another method of killing a thread exist in wpf?
1) Why?
Suspend method has been marked as Obsolete by Microsoft. Error states itself:
Thread.Suspend has been deprecated. Please use other classes in
System.Threading, such as Monitor, Mutex, Event, and Semaphore, to
synchronize Threads or protect resources.
2) It seems that some threads is still working even after the close of
the windows, Why this happens? How can i fix it?
You have started all threads as foreground thread which won't stop automatically when main thread finishes its execution. In case you want to stop all threads once all foreground threads stops, you should mark thread as background thread.
windowThread.IsBackground = true;
3) Is another method of killing a thread exist in wpf?
Use Thread.Abort(). However, closing your main thread will automatically stop all background threads (IsBackground set to true on thread), you should not worry about killing them.
What are you trying to do? You are creating threads just for the purpose of checking some condition? And when the condition is true, you change the visibility and block all threads(!) from further execution. And when the condition is not true, you create another thread that does the same. Why are you suspending all threads (including the active one) instead of just letting it terminate? And if you want to periodically check for a condition, use a timer or a wait event instead.
Just as a side note: Your foreach-loops will eventually throw InvalidOperationException, because you're changing the collection without a lock.
And then, don't try to kill threads. Use flags or signals instead. Any attempt to kill threads is a) bad design and b) prone to errors and unexpected behavior.
I have a kept a polling timer to check if a process is running or not. I have the following simple code for this:
bool alreadyChecked = false; //check if the wait to check the second time is already over
**Timer_elapsed event**
Process sampleProcess[] = Process.GetProcessesByName("notepad");
if(sampleProcess.length > 0)
{
//Process is running
return;
}
else
{
//Process is not running, so do the following
//Wait for some time and check again (set alreadyChecked = true when the wait is over)
if (alreadyChecked){
//Run the process}
else{
//The process has started running while we were waiting
return;}
}
I am not able to implement the waiting code inside the event, so that it can wait and then fire the event again. (Even if we implement the wait time, the Timer_elapsed event will be fired by timer again while we were waiting.)
Any suggestions?
You should create a separate thread and use the sleep method, using a BackgroundWorker is the best option. You can also use a timer thread.
**BackgroundWorker_DoWork event**
int nTrials = 0; // this method will help you pick any number of trials before launching the applicaion
bool isRunning = false;
while((isRunning = Process.GetProcessesByName("notepad") == 0) || nTrials < 2)
{
Thread.Sleep(1000); // w8 1 second before queriying the process name
nTrials++;
}
if ( isRunning ) RunProcess();
Don't use the sleep method on your main thread or your application will stop handling messages for the sleep time.
I am explaining my scenario, i have a function which print 1 to 10000 while printing i have to stop the process and let user know the current i value and if user presses enter it should continue again.
i am using
if ((Console.KeyAvailable) && (Console.ReadKey(true).Key == ConsoleKey.Escape))
but it doesn,t work, to complicate my task i am using threads, even if i manage to break this thread, child thread starts executing, i just want to stop the entire execution process for a moment and execute another function.
Check out the BackgroundWorker class, specifically, how to implement cancellation.
You'll basically need to check inside the loop if a cancellation is pending. If it is, then exit the loop.
If your using Threads. You can use this kind of code..
// Start
thread = new Thread(new ThreadStart(YourCommand));
thread.Start();
// Pause
if (thread != null)
{
thread.Suspend();
}
//Continue
if (thread != null)
{
thread.Resume();
}
//Alive
if (thread != null)
{
if (thread.IsAlive)
{
thread.Abort();
}
}
Or you can use timer....
In my current C#/NET 3.5 application, I have a task queue (thread safe) and I have 5 worker threads that has to constantly look for tasks in the queue. If a task is available, any one worker will dequeue the task and take required action.
My worker thread class is as follows:
public class WorkerThread
{
//ConcurrentQueue is my implementation of thread safe queue
//Essentially just a wrapper around Queue<T> with synchronization locks
readonly ConcurrentQueue<CheckPrimeTask> mQ;
readonly Thread mWorker;
bool mStop;
public WorkerThread (ConcurrentQueue<CheckPrimeTask> aQ) {
mQ = aQ;
mWorker = new Thread (Work) {IsBackground = true};
mStop = false;
}
private void Work () {
while (!mStop) {
if (mQ.Count == 0) {
Thread.Sleep (0);
continue;
}
var task = mQ.Dequeue ();
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;
task.IsPrime = IsPrime (task.Number);
task.ExecutedBy = Thread.CurrentThread.ManagedThreadId;
//Ask the threadpool to execute the task callback to
//notify completion
ThreadPool.QueueUserWorkItem (task.CallBack, task);
}
}
private bool IsPrime (int number) {
int limit = Convert.ToInt32 (Math.Sqrt (number));
for (int i = 2; i <= limit; i++) {
if (number % i == 0)
return false;
}
return true;
}
public void Start () {
mStop = false;
mWorker.Start ();
}
public void Stop () {
mStop = true;
}
}
Problem is that when queue is empty, it consumes too much CPU (nearly 98%). I tried AutoResetEvent to notify the workers that queue has been changed. So they effectively wait for that signal to set. It has braught down the CPU to nearly 0% but I am not entirely sure whether this is the best method. Can you suggest a better method to keep the threads idle without hurting CPU usage?
Check out this implementation of a BlockingQueue. If the queue is empty, it uses Monitor.Wait() to put the thread to sleep. When an item is added, it uses Monitor.Pulse() to wake up a thread that is sleeping on the empty queue.
Another technique is to use a semaphore. Each time you add an item to a queue, call Release(). When you want an item from a queue, call WaitOne().
You currently have Thread.Sleep(0) in your Work method for where there are no queue items. Change it to anything greater than 0 and your CPU use will go down. Try 10 to start with...
You have a couple of options that I can think of.
One way is to place a small thread sleep during your loop. This will basically drop your CPU usage to 0 and is fairly standard way of doing this.
Another way is to use a reset (either auto or manual) as suggested by Mitch Wheat in the comments.
You could also devise some kind of IdleTask that has a thread sleep for a certain amount of time and if your queue is empty, just process the IdleTask (which will thread sleep).
If your Queue is thread safe then you would not need to do this...
//Someone else might have been lucky in stealing
//the task by the time we dequeued it!!
if (task == null)
continue;