I'm creating a new thread and within the background thread method I do work and then call another method to do work.
myThread = new Thread(new ThreadStart(doWork));
myThread.Start();
The problem is that when I leave the background worker method to go to another method and execute this :
browser.SelectList(Find.ById("selStartYear")).SelectByValue(startYear);
I get an InvalidCastException.
When my background worker method is finished do I need to do something with the thread? I see that I started the thread, but calling abort on it in the new method it calls just suspends the program.
Edit: I'm using WakiN and created new IE in the global scope:
IE browser = new IE("http://www.website.com/");
My worker method references this as does the failing method.
No, you do not need to do any cleanup on a thread that has finished executing. You should actually strive never to call Abort, as that's a destructive method and providing a more "polite" means of signaling the thread that it should exit immediately is preferred to ending it violently with Abort.
Also, if your job is not particularly long-running, then you should probably be using either the new Task class available in System.Threading.Tasks or using System.Threading.ThreadPool.QueueUserWorkItem() instead of spinning up your own thread.
That being said, you aren't providing enough information to answer your InvalidCastException issue. What is the cast it's trying? What is the relation (if any) between the body of doWork and the values being used in your failing statement?
Adam provided a complete answer on threading issue. I just another hint. Your thread (as I see in sample code) is not a background thread. Also I think all multi-thread applications needs a plan for a graceful exit (consider a system shutdown).
To find out what's the source of casting error, I suggest breaking that line of code into 3 lines, since one of the parameters is not in the right type.
Related
I was learning about threads in C#. When I was writing some code, I learned to pause a thread, I should call the Thread.Sleep() function. It will pause the thread for the time I passed as parameter.
But to abort or start the thread, I need to use
Thread.CurrentThread.Abort()
Thread.CurrentThread.Start()
CurrentThread is also a Thread. So, I was expecting something like this
Thread.Sleep()
Thread.Start()
Thread.Abort()
or
Thread.CurrentThread.Abort()
Thread.CurrentThread.Start()
Thread.CurrentThread.Sleep()
Why is it different? What is the principle behind this?
I am not sure if it is a valid question or not. If It seems an invalid question to you please let me know, I will remove this question.
Abort() and Start() are instance methods of class Thread. You use them to interact with an existing Thread instance from the outside e.g. main thread.
Sleep() is a static method. You call it from within the running thread's context to cause it to pause.
How InvokeRequired and Invoke let us make our apps thread safe.
Let's consider such code:
private void ThreadSafeUpdate(string message)
{
if (this.textBoxSome.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(msg);
this.Invoke
(d, new object[] { message });
}
else
{
// It's on the same thread, no need for Invoke
this.textBoxSome.Text = message;
}
}
Is it possible to change state of InvokeRequired after InvokeRequired and before Invoke? If not, then why?
How does Invoking make it thread safe?
If InvokeRequired illustrate is current thread owning control, how would the thread know that it is or it is not the owner.
Let's consider that SomeMethod() is currently running on Thread1. We would like to call it from Thread2. Internally this method updates some field. Does Method.Invoke contain some kind of lock mechanism internally?
What if SomeMethod() takes very long time and we would like to run something other on the control owner thread. Does Invoking lock the owner thread or is it some kind of a background thread safe task?
ThreadSafeUpdate() //takes 5 minutes in Thread2
ThreadSafeUpdate() //after 2 minutes, we are running it in other thread2
ThreadSafeUpdate() //next run from Thread3
I think it is some kind of general pattern which can be implemented outside of winforms, what's its name?
Is it possible to change state of InvokeRequired
Yes, and it is a pretty common occurrence. Either because you started the thread too soon, before the form's Load event fired. Or because the user closed the window just as this code is running. In both cases this code fails with an exception. InvokeRequired fails when the thread races ahead of the window creation, the invoked code fails when the UI thread races ahead of the thread. The odds for an exception are low, too low to ever diagnose the bug when you test the code.
How Invoking make it thread safe?
You cannot make it safe with this code, it is a fundamental race. It must be made safe by interlocking the closing of the window with the thread execution. You must make sure that the thread stopped before allowing the window to close. The subject of this answer.
how would he know that he is or he is not owner.
This is something that can be discovered with a winapi call, GetWindowsThreadProcessId(). The Handle property is the fundamental oracle for that. Pretty decent test, but with the obvious flaw that it cannot work when the Handle is no longer valid. Using an oracle in general is unwise, you should always know when code runs on a worker thread. Such code is very fundamentally different from code that runs on the UI thread. It is slow code.
We would like to call it from Thread2
This is not in general possible. Marshaling a call from one thread to a specific other thread requires that other thread to co-operate. It must solve the producer-consumer problem. Take a look at the link, the fundamental solution to that problem is a dispatcher loop. You probably recognize it, that's how the UI thread of a program operates. Which must solve this problem, it gets notifications from arbitrary other threads and UI is never thread-safe. But worker threads in general don't try to solve this problem themselves, unless you write it explicitly, you need a thread-safe Queue and a loop that empties it.
What's if SomeMethod() takes very long time
Not sure I follow, the point of using threads is to let code that takes a long time not do anything to harm the responsiveness of the user interface.
I think it is some kind of general pattern
There is, it doesn't look like this. This kind of code tends to be written when you have an oh-shoot moment and discover that your UI is freezing. Bolting threading on top of code that was never designed to support threading is forever a bad idea. You'll overlook too many nasty little details. Very important to minimize the number of times the worker thread interacts with the UI thread, your code is doing the opposite. Fall in the pit of success with the BackgroundWorker class, its RunWorkerCompleted event gives a good synchronized way to update UI with the result of the background operation. And if you like Tasks then the TaskScheduler.FromCurrentSynchronizationContext() method helps you localize the interactions.
Usually, no. But it could happen if you're using await between the InvokeRequired check and Invoke call without capturing the execution context. Of course, if you're already using await, you're probably not going to be using Invoke and InvokeRequired.
EDIT: I just noticed that InvokeRequired will return false when the control handle hasn't been created yet. It shouldn't make much of a difference, because your call will fail anyway when the control hasn't quite been created yet, but it is something to keep in mind.
It doesn't make it thread-safe. It just adds the request to the control's queue, so that it's executed the next available time on the same thread the control was created on. This has more to do with windows architecture than with general thread-safety. The end result, however, is that the code runs on a single thread - of course, this still means you need to handle shared state synchronization manually, if any.
Well, it's complicated. But in the end, it boils down to comparing the thread ID of the thread that created the control, and the current thread ID. Internally, this calls the native method GetWindowThreadProcessId - the operating system keeps track of the controls (and more importantly, their message loops).
Invoke cannot return until the GUI thread returns to its message loop. Invoke itself only posts the command to the queue and waits for it to be processed. But the command is run on the GUI thread, not the Invoke-caller. So the SomeMethod calls in your example will be serialized, and the Invoke call itself will wait until the second call finishes.
This should already be answered. The key point is "only run GUI code on the GUI thread". That's how you get reliable and responsive GUI at all times.
You can use it anywhere you've got a loop or a wait on some queue. It probably isn't all that useful, although I have actually used it already a few times (mostly in legacy code).
However, all of this is just a simple explanation of the workings. The truth is, you shouldn't really need InvokeRequired... well, ever. It's an artifact of a different age. This is really mostly about juggling threads with little order, which isn't exactly a good practice. The uses I've seen are either lazy coding, or hotfixes for legacy code - using this in new code is silly. The argument for using InvokeRequired is usually like "it allows us to handle this business logic safely whether it runs in the GUI thread or not". Hopefully, you can see the problem with that logic :)
Also, it's not free thread-safety. It does introduce delays (especially when the GUI thread is also doing some work that isn't GUI - very likely in code that uses InvokeRequired in the first place). It does not protect you from accesses to the shared state from other threads. It can introduce deadlocks. And don't even get me started on doing anything with code that uses Application.DoEvents.
And of course, it's even less useful once you take await into consideration - writing asynchronous code is vastly easier, and it allows you to make sure the GUI code always runs in the GUI context, and the rest can run wherever you want (if it uses a thread at all).
Good morning,
I made a simple dll in which I use a WebBrowser control to do some simple tasks. Now I want to use its methods from the main UI in a separate Task or a BackgroundWorker. The problem is that whenever I use the methods I get the "no STAThread" exception... How can I get around this? Of course, in the dll there is no Main() method and I can't either add the STAThread attribute to the constructor.
Thank you very much.
Well, to get code running in a new STA thread you should create a new thread and explicitly force it to be an STAThread using Thread.SetApartmentState before starting it. You'll then need to use Control.BeginInvoke to marshal calls back to the UI thread - you don't want to use BackgroundWorker or Task, as those will use a threadpool thread.
On the other hand, it's not clear whether that will help in this case - if you're using a WebBrowserControl you'll probably need a message loop running etc.
It's not really clear what you mean by "use its methods from the main UI". Is this WebBrowserControl part of the UI which is running in the normal UI thread? If so, you'll need to marshal to that thread from the other thread (e.g. using Control.BeginInvoke) - and the other thread doesn't need to be an STA thread for that to happen.
I'm writing a bit of code that will open a MessageBox on a separate thread to prevent the MessageBox from stopping the program. It is very very important that starting a new thread will not crash the program that I am running, but I don't know enough about threads to make sure this happens.
My question is, after starting the thread, how can I safely dispose of it after the MessageBox closes? I imagine closing/disposing of it is necessary so it's not just floating around after it is created and started.
Please advise, thanks!
var Thread = new Thread
(
()=>
{
MessageBox.Show("Buy pizza, Pay with snakes");
}
);
Thread.Start();
You don't need to do anything special.
Thread instances are automatically "cleaned up" (rather they become candidates for garbage collection) when there's no references to them (in your code) and their main method body has terminated. In fact, Thread doesn't implement IDisposable - so speaking of it's "disposal" is incorrect.
In your example, once the lambda method completes (ie the message box is closed), the thread will automatically terminate. You don't need to do anything extra.
Now there's a difference between reclaiming allocated memory and having objects become candidates for disposal/collection. Any objects allocated will remain on the GC heap until the next collection cleans them up ... but you shouldn't have to care about that.
A separate issue you may need to contend with is performing UI operations on a thread other than the main UI thread. While it is possible, you have to be careful not to reference any UI elements that are created on a different thread from the one you create.
The thread will close automatically after the scope of the lambda expression is left... in your case you don't need to worry about anything.
In general it's also good practice to set the thread to background, because if your application is closed you might get a message box just hanging out there by itself:
var thread = new Thread(
()=>
{
MessageBox.Show("Buy pizza, pay with snakes");
});
thread.IsBackground = true;
thread.Start();
Note: it's preferred that your variables start with a lower letter. For details on naming conventions please see the Microsoft Naming Guidelines.
A Thread will automatically clean itself up once the code contained within it completes. You don't have to manually dispose of it (and, in fact, it's not IDisposable!).
A few things first...
Threads don't "crash" the program unless an unhandled exception is thrown from within it.
You don't need to dispose of a thread. Finishing its main routine is enough.
If necessary, you can make your program wait for the end of the thread execution using the Join() method on your Thread instance.
And then a suggestion: it seems that you need a modeless MessageBox. AFAIK, the feasible way of doing this is creating a custom form and display it through Show() instead of ShowDialog().
In C#, you shouldn't have to care all that much once the thread goes out of scope. It's a simple answer, but simple is good: let the computer do what it's good at. :-)
You should be aware that if an exception is thrown by your worker thread and is not caught, then your application may abort (as Humberto mentioned in point #1). The example you provided is trivial, and I can't imagine that it would throw an exception, but you may want to consider at least wrapping the worker thread logic in a try/catch.
I would suggest not using a separate thread for this purpose. Create your own form for displaying the message and show it with the Show method. Creating a form like this isn't too difficult; I recommend making use of the Button.DialogResult, Form.AcceptButton, and Form.CancelButton properties. You have more control over the appearance of the form
In terms of reliability, an advantage of keeping your code out of a worker thread is that you can subscribe to the Application.ThreadException event in order to handle any exceptions that were not caught by your application's logic. This allows you to prevent your application from crashing due to an unhandled exception, but be aware that this will affect your entire application.
I want to implement a timeout on the execution of tasks in a project that uses the CCR. Basically when I post an item to a Port or enqueue a Task to a DispatcherQueue I want to be able to abort the task or the thread that its running on if it takes longer than some configured time. How can I do this?
Can you confirm what you are asking? Are you running a long-lived task in the Dispatcher? Killing the thread would break the CCR model, so you need to be able to signal to the thread to finish its work and yield. Assuming it's a loop that is not finishing quick enough, you might choose to enqueue a timer:
var resultTimeoutPort = new Port<DateTime>();
dispatcherQueue.EnqueueTimer(TimeSpan.FromSeconds(RESULT_TIMEOUT),
resultTimeoutPort);
and ensure the blocking thread has available a reference to resultTimeoutPort. In the blocking loop, one of the exit conditions might be:
do
{
//foomungus amount of work
}while(resultTimeoutPort.Test()==null&&
someOtherCondition)
Please post more info if I'm barking up the wrong tree.
You could register the thread (Thread.CurrentThread) at the beginning of your CCR "Receive" handler (or in a method that calls your method via a delegate). Then you can do your periodic check and abort if necessary basically the same way you would have done it if you created the thread manually. The catch is that if you use your own Microsoft.Ccr.Core.Dispatcher with a fixed number of threads, I don't think there is a way to get those threads back once you abort them (based on my testing). So, if your dispatcher has 5 threads, you'll only be able to abort 5 times before posting will no longer work regardless of what tasks have been registered. However, if you construct a DispatcherQueue using the CLR thread pool, any CCR threads you abort will be replaced automatically and you won't have that problem. From what I've seen, although the CCR dispatcher is recommended, I think using the CLR thread pool is the way to go in this situation.