say we declare and run a thread in a method which has a while(1) loop. How can one avoid to create and run a second thread when the method is called again?
I only want one thread to start in this method and every time the method is called again, there should be no thread creation all over again. Should I check for the thread name or should I declare the thread as a field of the class?
Any ideas how to do this?
Thanks,
Juergen
It sounds like the thread should indeed be a field of the class - although you'll have to be careful to access it in a thread-safe way, if there could be several threads calling the method to start with.
What do you want to happen the second time - should the method block, or just finish immediately, or perhaps throw an exception? If you don't need to wait for the thread to finish, you might be able to get away with just a flag instead of keeping a reference to the thread itself.
(Note that I've been assuming this is an instance method and you want one extra thread per instance.) If that's not the case, you'll have to adjust accordingly.
Have the method return a singleton, and start the thread in the singleton constructor.
Could you save the synchronization context the first time, check on subsequent times to see if it matches, and post back to it if necessary?
SynchronizationContext syncContext = null;
...
// "object state" is required to be a callback for Post
public void HiThar(object state) {
if (syncContext == null) {
syncContext = SynchronizationContext.Current;
} else {
syncContext.Post(HiThar, state);
}
}
Related
A question about Dispatcher.BeginInvoke
If I have a method as follows:
private void DoSomeWork()
{
MyCanvas.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate
{
//Do something
return null;
}), null);
}
And I call the method multiple times, then the multiple calls are executed in the order they are created as per docs: If multiple BeginInvoke calls are made at the same DispatcherPriority, they will be executed in the order the calls were made. Dispatcher.BeginInvoke Method MSDN
How does one clear this to stop another call being made or to reset the queue to just a single call?
How does one clear this to stop another call being made or to reset the queue to just a single call?
You don't. You don't get to control the dispatcher queue. What you could do is keep a count of "pending requests" (making sure you update it atomically, of course) and only execute if this is the last call in the queue (i.e. when decrementing the count gives 0).
Another option would be to keep some sort of timer for when the last call was made, and ignore further calls within some period of time.
If you could give more details about what you're trying to achieve, we could give more concrete help.
The MSDN link that you provided gave you the answer with a little more digging.
This operation returns a DispatcherOperation object that can be used to cancel. But, that is on a per call basis, as you cannot control the queue in its entirety.
I'm running heavvy background work with Parallel.Invoke, after all processing has completed I return the method, return again, call a next method to utilize the calculated data I get the error:
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
But I already returned from the threads that where created by Parallel.Invoke to the one that called it in the first place. Is it normal that control does not revert to the thread where it started? And how can I assure that this does happen?
Code:
public void TopMethod()
{
Calculate(4);
UpdateGui();
}
public void Calculate(int depth)
{
Recursive(depth);
}
public void Recursive(int depth)
{
if (depth > 0)
System.Threading.Tasks.Parallel.Invoke(
delegate { Recursive(depth - 1); });
}
public void UpdateGui()
{
CalculateOhter(); // Works fine.
controlElement.Focus(); // Causes exception
}
Edits:
I know about Control.Invoke But this would be an ugly solution (don't want to store a delegate in every control) and the program needs to wait for all computations to complete before it can continue. So it would be better if I could somehow force control to return to the thread that I started out with in the first place.
You need to access a control/window from the thread that created that control. Use Control.Invoke and Control.InvokeRequired.
The horrible way to do is to set Control.CheckForIllegalCrossThreadCalls to false. It should get rid of your error, but it is not good design.
The problem with that occurs when a thread other than the creating thread of a control tries to access one of that control's methods or properties, it often leads to unpredictable results.
The example for Control.Invoke involves storing a Delegate, can this be done without storing a delegate for every control? So passing the method I need to call as an argument to the Invoke call (tried this but cannot get it to work).
The program needs to wait for all computations to complete before it can continue so it would be better if I could somehow force control to return to the thread that I started out with in the first place.
I don't understand why this does not happen at default, why does it not just return to the thread it started with when everything is complete?
Solved it, turns out I created a seperate thread to call the given code in the first place, kinda stupid :P
What I have is a loop reading some data and when a set of circumstances are met I need to instantiate a thread. However, the created thread might not complete before the loop criteria is met and I need to create another thread doing the same thing. This is part of an ocr app and I haven't done much thread work before.
while loop
if(criteria)
{
observer = new BackgroundWorker();
observer.DoWork += new DoWorkEventHandler(observer_DoObserving);
observer.RunWorkerAsync();
}
the observer_DoObserving function calls the ocr app, waits for a response and then processes it appropriately and sets observer = null at the end. So how would I create multiple instances of the 'observer' thread. Of course instantly I thought of a class structure, is this an appropriate way to do it or is there another way that is appropriate for threading.
I hope this makes sense.
Thanks, R.
You could use the thread pool, specifically ThreadPool.
while (something)
{
if (criteria)
{
// QueueUserWorkItem also has an overload that allows you to pass data
// that data will then be passed into WorkerMethod when it is called
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkerMethod));
}
}
// ...
private void WorkerMethod(object state)
{
// do work here
}
How you handle this depends in large part on whether the background thread needs to communicate anything to the main thread when it's done. If the background thread really is "fire and forget", then there's no particular reason why you need to maintain a reference to the observer. So you could write:
while loop
{
if(criteria)
{
BackgroundWorker observer = new BackgroundWorker();
observer.DoWork += new DoWorkEventHandler(observer_DoObserving);
observer.RunWorkerAsync();
}
}
The thread does its work and goes away. observer is a local variable that goes out of scope when execution leaves the if block. There's no way that the variable will be overwritten if you have to start another observer thread before the first one is finished.
If you need to keep track of information for individual observers, then you'd create an object of some type (a class that you define) that contains information about the worker's state, and pass that to the RunWorkerAsync method. The worker can then modify that object and send you progress notifications (see the ProgressChanged event and the ReportProgress method), and also report the status when the worker has finished (see RunWorkerCompleted, the state object you passed to RunWorkerAsync will be in the RunWorkerCompletedEventArgs.UserState property).
I am not entirely able to grasp what you are doing exactly, so I may or may not be helpful here;
You seem to be, in part, asking if it's appropriate to create a class to hold some data indicating the state of a thread or what it's working on. That is entirely appropriate to do, provided the object is not an 'expensive' one to create. (no creating Exception objects and throwing them around all the time, for instance).
I have following problem:
I want to check (C#) if a thread has finished execution, i.e. if the thread method has returned. What I do now is call Thread.Join(1), but this gives a 1 ms delay. Is there any way to simply check if a thread has finished. Inspecting Thread.ThreadState just seems too cumbersome.
Use the Thread.IsAlive flag. This is to give the thread status.
For a thread you have the myThread.IsAlive property. It is false if the thread method returned or the thread was aborted.
If you don't want to block the current thread by waiting/checking for the other running thread completion, you can
implement callback method like this.
Action onCompleted = () =>
{
//On complete action
};
var thread = new Thread(
() =>
{
try
{
// Do your work
}
finally
{
onCompleted();
}
});
thread.Start();
If you are dealing with controls that doesn't support cross-thread operation, then you have to invoke the callback method
this.Invoke(onCompleted);
You could fire an event from your thread when it finishes and subscribe to that.
Alternatively you can call Thread.Join() without any arguments:
Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping.
Thread.Join(1) will:
Blocks the calling thread until a thread terminates or the specified time elapses, while continuing to perform standard COM and SendMessage pumping.
In this case the specified time is 1 millisecond.
Use Thread.Join(TimeSpan.Zero) It will not block the caller and returns a value indicating whether the thread has completed its work. By the way, that is the standard way of testing all WaitHandle classes as well.
I use IsAlive extensively, unless I want to block the current execution (of the calling thread), in which case I just call Join() without a parameter. Now, be aware that IsAlive may return false if the target thread has not actually started execution yet for any reason.
Carlos Merighe.
It depends on how you want to use it. Using a Join is one way. Another way of doing it is let the thread notify the caller of the thread by using an event. For instance when you have your graphical user interface (GUI) thread that calls a process which runs for a while and needs to update the GUI when it finishes, you can use the event to do this. This website gives you an idea about how to work with events:
http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx
Remember that it will result in cross-threading operations and in case you want to update the GUI from another thread, you will have to use the Invoke method of the control which you want to update.
Take a look at BackgroundWorker Class, with the OnRunWorkerCompleted you can do it.
I am working on a small project where I need to make two asynchronous calls right after another.
My code looks something like this:
AsynchronousCall1();
AsynchronousCall2();
The problem I'm having is that both calls take anywhere from one to two seconds to execute and I never know which one will finish last. What I'm looking for is a way to determine who finishes last. If Call1() finishes last, I do one thing. If Call2() finishes last, I do another thing.
This is a simple example of using a lock to ensure that only one thread can enter a piece of code. But it's a general example, which may or may not be best for your application. Add some details to your question to help us find what you're looking for.
void AsynchronousCall1()
{
// do some work
Done("1");
}
void AsynchronousCall2()
{
// do some work
Done("2");
}
readonly object _exclusiveAccess = new object();
volatile bool _alreadyDone = false;
void Done(string who)
{
lock (_exclusiveAccess)
{
if (_alreadyDone)
return;
_alreadyDone = true;
Console.WriteLine(who + " was here first");
}
}
I believe there is a method that is a member of the Thread class to check on a specific thread and determine its status. The other option would be to use a BackgroundWorker instead, as that would allow you to spell out what happens when that thread is finished, by creating seperate methods.
The "thread-unsafe" option would be to use a class variable, and at the end of each thread if it isn't locked / already have the other thread's value, don't set it. Otherwise set it.
Then when in your main method, after the call to wait for all threads to finish, test the class variable.
That will give you your answer as to which thread finished first.
You can do this with two ManualResetEvent objects. The idea is to have the main thread initialize both to unsignaled and then call the asynchronous methods. The main thread then does a WaitAny on both objects. When AsynchronousCall1 completes, it signals one of the objects. When AsynchronousCall2 completes, it signals the other. Here's code:
ManualResetEvent Event1 = new ManualResetEvent(false);
ManualResetEvent Event2 = new ManualResetEvent(false);
void SomeMethod()
{
WaitHandle[] handles = {Event1, Event2};
AsynchronousCall1();
AsynchronousCall2();
int index = WaitHandle.WaitAny(handles);
// if index == 0, then Event1 was signaled.
// if index == 1, then Event2 was signaled.
}
void AsyncProc1()
{
// does its thing and then
Event1.Signal();
}
void AsyncProc2()
{
// does its thing and then
Event2.Signal();
}
There are a couple of caveats here. If both asynchronous methods finish before the call to WaitAny, it will be impossible to say which completed first. Also, if both methods complete very close to one another (i.e. call 1 completes, then call 2 completes before the main thread's wait is released), it's impossible to say which one finished first.
You may want to check out the Blackboard design pattern: http://chat.carleton.ca/~narthorn/project/patterns/BlackboardPattern-display.html. That pattern sets up a common data store and then lets agents (who know nothing about one another -- in this case, your async calls) report their results in that common location. Your blackboard's 'supervisor' would then be aware of which call finished first and could direct your program accordingly.