I need to ensure that, once the execution hits a method, the control received by this method is not changed by another thread.
Basically, I thought in something like this:
private void doSomeWork(Control control) {
lock (control) {
// do some stuff with the control...
}
}
Is this a bad idea?
Edit:
Actually, what I'm trying to do, is to ensure that the control will not disposed by another thread while I execute some of the control's methods (which, by the way, will be executed via reflection).
In a well behaving application, windows forms controls are already restricted to only one thread. If any thread tries to access a control created in a different thread, an exception will be thrown.
There is nothing wrong about your code, just know that right now it's mostly useless unless you are hacking your way through the protection (which is possible).
Usually, when you have data being created or manipulated in a working thread, the working thread will send an event to the UI thread to update the UI. In no way should a working thread updates the UI itself, it will automatically fail.
Actually Fernando, it's not a bad idea but it's not the correct way to look at locking. You need to closely read what the lock statement does in .Net:
http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.80).aspx
i think that from your statement you expect the whole object to be locked, or somehow be made safe for threading, because the object iteself is used in a locked block of code. What actually happens is that block of code is locked and not allowed to be executed by two or more threads at the same time. If that block of code is the only place you're going to be operating on the control then you're ok, otherwise you'll need to do synch locks on the object itself.
Don't have a lot of experience working with threads, but, maybe I'll suggest you to start the Form Control in a new thread using an anonymous delegate:
t= new Thread(delegate() {
MyMethodToInvokeTheWinFormControl();
});
t.Start();
It depends entirely on what you mean by "not changed".
If your meaning is "any other thread cannot change this control, at all, in any way", then that's not how lock works.
A lock in this sense is not like a regular lock on a door to a house. It's more like a small yellow post-it note that says "Locked". As long as other threads read the note and abide by what it says, it should be fine, but any other thread that doesn't care about the note at all will of course not be prevented from messing with your control.
In any case, what exactly are you trying to accomplish? You should never be messing with controls from other than the main thread so the problem shouldn't exist in the first place.
Instead you should be marshalling all work on the control onto the main thread through the use of the Invoke method on the control.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why .NET does not allow cross-thread operations?
Why is only the UI thread allowed to modify the UI?
From what I have understood, the reason .net raises the illegal cross thread calls exception is that the GUI might show indeterministic behaviour.
But isn't this the case with every other object? If two threads work on the same object, depending on the code, the object might be in an indeterministic situation. So why does this exception exist for control elements? Or why is this exception exclusive to control elements.
And how is using invoke going to help? It will still be indeterministic.
Invoke-ing controls on other threads is required because cross-thread calls to Controls are not allowed. For a more complete discussion as to why this restriction exists you should have a read of that link - I'm not going to answer that here, it just is (however be assured that this restriction exists for a good reason).
Calling Invoke helps us because it allows a background thread to "do stuff" on a UI thread - it works because it doesn't directly call the method, rather it sends a Windows message that says "run this when you get the chance to". The UI thread is running a message pump which continuously processes all messages sent to that thread - often these messages are things like "the user clicked on this button", in which case Windows Forms handles this message by raising the Click event on the relevant control. In this case Windows Forms handles the message by running the supplied delegate.
The result is that only 1 thread is modifying / working with the UI controls at any one point in time (the UI thread).
Note that Invoke makes no guarentees as to the order in which delegates will be run. If its important that two delegates being Invoked from two different threads (or even the same thread) be executed in the correct order then thats a different problem.
Aside: We talk about "the UI thread" because most applications have one thread on which all controls are created, however in reality different controls can be created threads - its the thread that the control was created on which process the message. Obviously in order for those messages to be properly processed there must be a message pump running on that thread.
Most types aren't actually thread safe, but can be used from multiple threads so long as only one thread uses them at a time.
UI controls aren't quite the same: they have thread affinity - they can only be safely used on the UI thread.
Part of the reason for this is that the UI thread may want to redraw them at any time, so they've got to be available at any time. Combine that with not wanting to delay the UI thread while it waits for a lock, and also combine it with the desire to avoid even uncontested locking if you can help it (and the UI thread would have to take out a lot of locks if it needed to do this for every access) and you get a simplified model where it's easier just to say that all access must be on the UI thread. I'm sure it would be possible to design a UI framework without thread affinity, but getting it to perform and behave predictably would be tricky.
Invoke is used to make sure you are calling the UI on the correct thread. but this is needed for every .net object. The UI is made to work on a single thread(this is true with WPF and Winforms). Two different threads can access the same object as long as its not at the same time. If it this happens it creates a race case and could end in dead lock
I have a problem that I don't want to work with multithreaded applications since I am testing some code, and I need it single threaded.
It's updating the textbox only after it's all done. I need to somehow keep it updated all the time. Is there another way except with a second thread?
It's updating the textbox only after it's all done. I need to somehow keep it updated all the time. Is there another way expect with a second thread?
There isn't a good way to do this. The problem is, if you're executing code on the UI thread, the UI thread can't process the messages in the message pump, including the ones that way to refresh the TextBox, until your work completes.
In Windows Forms, you can force the application to process these messages by calling Application.DoEvents(), but this is really a bad, bad idea. It's much better (and safer!) to use a BackgroundWorker or some other multithreading technique to push the work into the background thread instead.
You could try the following:
// in for loop
tbxMyTextBox.Text = "New text!";
tbxMyTextBox.Refresh();
I remember having to do something similar in the past.
I have a windows form with some controls on it. One of the controls is a textbox and the other one is listView. I also have a button (Upload) that uploads files based on the items selected item ListView object.
To report upload progress %, i added a progress bar that created a background worker thread that would upload the files, by contacting the server. The progress bar does not updates properly and appears unresponsive without the approach of creating background worker.
Now, while uploading files, i need to get the selection from ListView and get files based on that selection. But when i try to access "ListView" from background worker thread I get an exception: System.InvalidOperationException: Cross-thread operation not valid:
What should i do to correct this exception?
In this case your processing thread wants to access your UI thread.
Example:
private delegate void UpdateTextDelegate(object value);
private void UpdateText(object value)
{
if (this.textbox.InvokeRequired)
{
// This is a worker thread so delegate the task.
this.textbox.Invoke(new UpdateTextDelegate(this.UpdateText), value);
}
else
{
// This is the UI thread so perform the task.
this.textbox.Text = value.ToString();
}
}
Access to Windows Forms controls is not inherently thread safe. If you have two or more threads manipulating the state of a control, it is possible to force the control into an inconsistent state. Other thread-related bugs are possible as well, including race conditions and deadlocks. It is important to ensure that access to your controls is done in a thread-safe way.
The .NET Framework helps you detect when you are accessing your controls in a manner that is not thread safe. When you are running your application in the debugger, and a thread other than the one which created a control attempts to call that control, the debugger raises an InvalidOperationException with the message, "Control control name accessed from a thread other than the thread it was created on."
This exception occurs reliably during debugging and, under some circumstances, at run time. You are strongly advised to fix this problem when you see it. You might see this exception when you debug applications that you wrote with the .NET Framework prior to .NET Framework version 2.0
BackgroundWorker also uses a thread to do it's job.
Look at this
No code should touch any Control unless it's running on the UI thread. This means invoking methods (other than Control.Invoke()) and setting/retrieving properties. The best way to accomplish this is to make liberal use of Control.InvokeRequired and Control.Invoke(). For your particular case, you may want to look into using a BackgroundWorker to do your file uploading.
You cannot access controls created on one thread from another thread. This is a good thing, trust me. The BackgroundWorker class exposes a couple of events that can help you accomplish what you want, namely ProgressChanged and RunWorkerCompleted.
I wrote a detailed guide to some of the techniques to handle this on a forum I frequent. Look at the explanation under the "Classic Marshalling" header for a walkthrough of what the implementation looks like.
Usually, I use the ReportProgress method of the BackgroundWorker component to marshall elements from the background thread to the UI thread.
You can simply pass the progress (integer) value and you can as well pass complex objects (non-GUI only, so no ListViewItems or the like) to the GUI thread in this event.
The good solution would be using Control.Invoke/Control.InvokeRequired - it helps executing code in the GUI thread (thus not throwing an exception).
The bad/ugly solution would be Control.CheckForIllegalCrossThreadCalls = false.
I've seen the common setup for cross threading access to a GUI control, such as discussed here:
Shortest way to write a thread-safe access method to a windows forms control
All the web hits I found describe a similar thing.
However, why do we need to check InvokeRequired? Can't we just call Invoke directly?
I assume the answer is no, so my real question is 'why'?
From non-UI threads we can't touch the UI - very bad things can happen, since controls have thread affinity. So from a non-UI thread we must (at a minumum) call Invoke or BeginInvoke.
For UI-threads, however - we don't want to call Invoke lots of time; the issue is that if you are already on the UI thread, it still has the unnecessary overhead of sending a message to the form's pump and processing it.
In reality, in most threading code you know you expect a specific method to be called on a non-UI thread, so in those cases, there is no additional overhead: just call Invoke.
If you try to invoke before a window handle is created (for example, when calling form constructor), you will get an InvalidOperationException. So, generally InvokeRequired check is required.
See MSDN for details.
InvokeRequired basically tells you if you're executing on the right thread or not. If you're not on the correct thread, you need to marshal the task to the correct thread otherwise you don't. Hence the need for the check.
The issue is that GUI controls have a requirement that only code executing on the same thread that was used to instantiate the GUI control can access the GUI control. The reasons behind this requirement are tied to the way that Windows is architected. Suffice to say, it would very difficult to change this.
The InvokeRequired checks the identity of the current executing thread against the identity of the instantiating thread. If they are the same, the code can freely interact with the control. If not, the code must marshal the data across from the current thread to the instantiating thread. This is a slow and costly process and is to be avoided if at all possible. Your code will work if you always invoke and it may be that you will not notice the performance hit, but this scenario is going to be increasingly common as multi-core systems come into use. It is best not to create code "knots" that have to be undone later.
One reason I can think of is performence.
If most of the time the calling thread is the same as the creating thread then you'll have some unnessecry overhead.
The Invoke is going to call the code through Delegate and not directly which would be costly.
Its cost effective to call Invoke only when it required. Hence, InvokeRequired is used to find out is the call being made from same thread or another thread?
Or is it okay to do something like this:
new Thread( new ThreadStart( delegate { DoSomething(); } ) ).Start();
?
I seem to recall that under such a scenario, the Thread object would be garbage collected, but the underlying OS thread would continue to run until the end of the delegate passed into it. I'm basically looking for ThreadPool functionality, but don't want the threads to be background threads (i.e. I want them to keep the app alive).
Update:
According to Jason, the CLR actually keeps an internal reference to the Thread object, while running, so it won't be garbage collected until the thread exits.
I have generally found that if I need to directly start a new thread the way you are in your example, rather than grabbing one from the thread pool, then it is a long running thread and I will need a reference to it later to kill it, monitor it, etc. For short run threads like invoking IO on a background thread, etc, I always use a thread pool thread (usually indirectly through a someDelete.BeginBlah(...) method call). When using a thread pool thread like this I prefer to NOT keep a reference around. I don't know if another programmer might inappropriately use a reference to that thread. If I don't need a reference, I don't keep it around to clutter up code.
Edit: To answer your edit about threads being garbage collected, this will not occur while the thread is running. The CLR keeps a reference to every running thread. The object representing the thread will NOT be collected.
It depends. In the situation where the user can cancel the operation of your thread, you should keep the reference so the thread can be canceled when the user want. In other situations, there may be no need to store the reference.
I have had a number of cases in production code where doing this has been appropriate. So, yes defining and starting a thread in one line without retaining a reference has it's place. I think keeping a reference "just in case" you redesign later and need it is failing the principle of creating the simplest thing that works.
And, to the second part, no it will not be GC'd while it is running; threads are root level objects from which the GCtor will chase down references. The Thread instance will only be GCd once it is no longer reachable by any running thread including the one which you start on it.
And beware leaking Thread instances which are created but never started. I believe they will hang around forever.
It might be good to ask the question "How often can this thread be started up?" Is it per-application, per-class, per-object instance, or per-method invocation? This may tell you what kind of variable (if any) to store it in.
Yes, you should, because you never know when you will have to change the code later to handle the thread in some way. That, and putting too much stuff on one line like that is just ugly.
So truthfully, you can do it your way, so the answer really comes down to code style preference.
In addition to what "m3rLinEz" has posted above, another draw back is that if any exception occurs in your thread it will be hard to even detect such cases.