I am working on application which calls a function populate() on window_load
This function execution takes about 1 minute to complete. I wanna make this function to be called in separate thread.
I am using following code
Thread thread = new Thread(PopulateAndDrawGraph);
thread.Start();
in this function at last line is
nodeXlControl1.DrawGraph(true);
Here exception occurs
The calling thread cannot access this object because a different thread owns it.
what wrong is actually occurs
You are only allowed to access UI controls from within the same thread that created the control, which is usally the UI thread itself.
You will need to change your code in a way that it becomes thread-aware.
Here is a fantastic article that was published in the MSDN magazine: Give Your .NET-based Application a Fast and Responsive UI with Multiple Threads, which will explain in great detail how you can do what you want to do.
The article is a little old, but the same principles still apply.
I guess that the newer C# language features - like the new async / await keywords - should make your task a little easier.
But keep in mind that the same old limitations for accessing UI controls still exist. There is no way around to understand the basics as descripbed in the article.
There are 2 ways to handle this, a correct way and another way:
1: If you want a good working solution then this should do the trick, ..
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
msdn.microsoft.com/en-us/library/ms171728.aspx
2: but if you want a quick solution without guarantee that it will work properly, just set this variable:
Control.CheckForIllegalCrossThreadCalls = False
The problem is, that the any UI interaction has to occur in the main thread of the application. My advice is that you draw make the computation in the separate thread, but collect your results in an object. After the thread is finished you can extract the result from that object, and place it the nodeXlControl1.
Sadly i don't know the details about your objective, the sum of the solution is this.
If u can tell more details about this i may be able to further help you.
check this article (How to: Make Thread-Safe Calls) here out. It explains all the related items regarding cross thread calls. I also recommend that you look into the concept of "Task" in c#. Theres a very well written lib that helps you handle parallelism and similar concepts!
Since you are trying to access a UI element from a thread you need to call Invoke. So in PopulateAndDrawGraph you should have:
Invoke((Action)(() =>
{
nodeXlControl1.DrawGraph(true);
}));
You can't access the UI controls from any other thread except the thread which has created this control(you can access/change the UI control properties from the main UI thread only). Go through this link, i hope this makes you clear Cross-thread operation not valid
I have used BackgroundWorker class in c#.
Related
I've found what looks like a very simple solution to my current situation.
My current situation is that I want to do some I/O-heavy operations on a new Thread, so that I do not bog down my GUI Thread. I have a function written, as a member of my Form, that does these I/O operations already, but running it on the GUI Thread really makes the application a pain to use. So my plan was to just run this function in a new Thread. So, I created a Thread variable, in my form, and am trying to get it to use that function as the ThreadStart parameter. It does not seem to like it, though.
I found an elegant looking solution, as a response to another thread, here.
///...blah blah updating files
string newText = "abc"; // running on worker thread
this.Invoke((MethodInvoker)delegate {
someLabel.Text = newText; // runs on UI thread
});
///...blah blah more updating files
From the looks of that response, I could run this function in a new Thread and then use an anonymous function to update my Form when the Thread has finished its calculations. I'm just not good enough to fill in the blanks from that response, though.
Everything I seem to read about Threads says that my ThreadStart function needs to be a static method in a new class. That response seems to suggest that I can do it within my Form class though, so that the this reference still references my Form instance. Otherwise, if my ThreadStart parameter were a different class, I'd have to pass in references to the Form instance, and that seems like more code, right?
Would anybody mind helping me fill in the context for that response? Thanks in advance!
There are a lot of ways you can do this. A very simple, straightforward one that's been around for a number of versions is to use the BackgroundWorker. It is designed for exactly this case. It has a DoWork method that runs in a background thread, and a Completed event that is fired after the work is done which runs in the UI thread (so you don't need to call invoke or anything to update the UI with the results). It even has support built in for reporting progress (the report progress event also runs in the UI thread) so you can easily update a progress bar or status text.
MSDN has some examples as well, and you can find lots more through some simple searches.
Another option, made available through C# 4.0, is to use Tasks. You can start a new task which will be run in a background thread, and then you can add a continuation which will be in the UI thread.
Here is a simple example:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => doStuffInBackground())
.ContinueWith(task => updateUI(), TaskScheduler.FromCurrentSynchronizationContext());
}
private void updateUI()
{
throw new NotImplementedException();
}
private void doStuffInBackground()
{
throw new NotImplementedException();
}
You can of course do whatever you want in the actual lambdas that I have there, or you could even remove the lambdas and put methods in there directly as long as you ensure the signatures are correct. You could also continue chaining these continuations if you wanted, allowing you to, for example, to task 1, update a label, then do task 2, update a label, etc. The main disadvantage is that it's not good at updating a progress bar frequently inside of a loop, the way a BackgroundWorker can.
I see a lot of threads on google/here on UPDATING a UI element from another thread.
What if I want to just get the value of a checkbox?
Am I able to do this without having to do anything special?
Edit: It seems I have to take back what I wrote before. Tried the following:
Added a textbox called myTextBox and tried to retrieve the value of the Text property:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
string value = myTextBox.Text;
Thread.Sleep(2000);
});
t.Start();
And it seems that the app (WPF) crashes after 2 seconds. Using the dispatcher works:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
myTextBox.Dispatcher.BeginInvoke(
(Action)(() => { string value = myTextBox.Text; }));
Thread.Sleep(2000);
});
t.Start();
Thus, you still need to go through the dispatcher thread when reading values from GUI components, at least in WPF.
Second edit: This gets better. Apparently repeating the experiment for classic WinForms reveals that it works to read the Text property without using Invoke/BeginInvoke. Interestingly enough, it seems that also setting the property works fine (without invoke), although I'll wager it's not thread safe and the app doesn't complain for some reason.
Bottom line: It's a good idea in any case to use the dispatcher when interacting with GUI components from other threads, as it ensures the reads/writes are serialized to a single thread and so you have no thread-safety issues.
Can you access UI elements from another thread? (get not set)?
No.
Here is the deal. UI elements have very strict thread affinity requirements. This means you can only access the element from the thread hosting it. This includes all kinds of accesses including simple reads.1
It may work fine for simple property getters, but its perceived safeness would be an accidental result of the way that particular control was implemented. Since Control instances have thread affinity they could potentially use thread local storage techniques to save some of their state which, of course, would not be compatible with different thread. Or what if the value you are trying to read is in a half-baked state? There would be no way to synchronize access to that read since the write may be occurring inside code you have no control over. And still this is ignoring subtle memory barrier problems that may arise.
Again, if it appears to work then chalk it up as an accident. Accessing UI elements from a thread than the one hosting them is a recipe for disaster. Things may fail unpredictably and spectacularly.
1There are very few exceptions to this rule. Using the ISynchronizeInvoke methods is one such exception.
You could but strictly it wouldn't be thread safe.
For instance if the property Get code would consist of multiple operations, the UI thread could act in the mean time, halfway during the Get operation, causing unexpected results.
simply read the value as you normally do. Only to update the control, you need to switch to GUI thread.
I've been researching on how to do this for about a week and I'm still not sure about the correct approach, in some examples I see the Thread class is used in others I see Invoke is used which has confused me a bid.
I have a GUI program in c# which contains a textBox which will be used to give information to the user.
The problem I'm facing is that I'm not sure how I can append text to textBox from another class which is running on another thread. If someone can show me a working example, it would help me greatly.
Best Regards!
Easy:
MainWindow.myInstance.Dispatcher.BeginInvoke(new Action(delegate() {MainWindow.myInstance.myTextBox.Text = "some text";});
WHERE MainWindow.myInstance is a public static variable set to the an instance of MainWindow (should be set in the constructor and will be null until an instance is constructed).
Ok thats a lot in one line let me go over it:
When you want to update a UI control you, as you say, have to do it from the UI thread. There is built in way to pass a delegate (a method) to the UI thread: the Dispatcher. I used MainWindow.myInstance which (as all UI components) contains reference to the Dispatcher - you could alternatively save a reference to the Dispatcher in your own variable:
Dispatcher uiDispatcher = MainWindow.myInstance.Dispatcher;
Once you have the Dispatcher you can either Invoke() of BeginInvoke() passing a delegate to be run on the UI thread. The only difference is Invoke() will only return once the delegate has been run (i.e. in your case the TextBox's Text has been set) whereas BeginInvoke() will return immediately so your other thread you are calling from can continue (the Dispatcher will run your delegate soon as it can which will probably be straight away anyway).
I passed an anonymous delegate above:
delegate() {myTextBox.Text = "some text";}
The bit between the {} is the method block. This is called anonymous because only one is created and it doesnt have a name - but I could instantiated a delegate:
Action myDelegate = new Action(UpdateTextMethod);
void UpdateTextMethod()
{
myTextBox.Text = "new text";
}
Then passed that:
uiDispatcher.Invoke(myDelegate);
I also used the Action class which is a built in delegate but you could have created your own - you can read up more about delegates on MSDN as this is going a bit off topic..
Sounds like you're using a background thread for processing, but want to keep the UI responsive? The BackgroundWorker sounds like the ticket:
The BackgroundWorker class allows you
to run an operation on a separate,
dedicated thread. Time-consuming
operations like downloads and database
transactions can cause your user
interface (UI) to seem as though it
has stopped responding while they are
running. When you want a responsive UI
and you are faced with long delays
associated with such operations, the
BackgroundWorker class provides a
convenient solution.
Just use BackgroundWorker for the same. It is simple and takes away the pain of managing threads of your own. for more, you can see: http://dotnetperls.com/backgroundworker
I have a lot of long-running activities and think that spawning this activity off to another thread will be a good way to have my U.I be able to update to show its current status.
However, when I use the following:
Thread t = new Thread(() =>
{
/* do magic here */
});
Nothing inside the foreach loop that's inside the thread gets done. But, when I don't use a thread, the work does get done, so I know it's not a problem with the loop.
Any suggestions?
You may also want to take a look at BackgroundWorker as it nicely encapsulates everything.
Are you even starting the thread?
newThread.Start();
In the sample you provide you merely declare it.
Also bear in mind that if you're using WinForms, you won't be able to update the UI directly from any thread other than the one that created it; for example, modifying a progress bar or label control from within your foreach loop.
You need to start the tread, t.Start();
Creating the instance just creates an managed wrapper for a thread. Calling Start will set things in motion and eventually make your code run on a separate thread.
Probably you haven't started the thread, so its not running yet.
However, in your case its usually better to use BackgroundWorker class, this will create the thread for you and provide thread-safe way to update the UI with the progress of the threads work.
What do I want to achieve: I want to perform some time consuming operations from my MDI winforms application (C# - .NET).
An MDI child form may create the thread with the operation, which may take long time (from 0.1 seconds, to even half hour) to complete. In the meantime I want the UI to respond to user actions, including manipulation of data in some other MDI child form. When the operation completes, the thread should notify the MDI child that the calculations are done,
so that the MDI child can perform the post-processing.
How can I achieve this:
Should I use explicit threading (i.e., create explicit threads), thread pools? Or simply just propose your solution. Should I create foreground or background threads?
And how does the thread communicates with the GUI, according the solution you propose?
If you know of a working example that handles a similar situation, please make a note.
I think you are looking for the BackgroundWorker class. Example
Use the BackgroundWorker class. It does just what you're looking for:
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(LongRunningCode);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CallbackOnCompletion);
backgroundWorker.RunWorkerAsync();
Also, to update your UI from the background thread, you need to call Invoke on your UI element.
This depends, slightly.
In general, I agree with BFree that the BackgroundWorker is likely the best option here. I makes notification back to the UI simple, etc.
That being said, the only reason I'm posting, and questioning whether you may want to use BackgroundWorker is this statement:
which may take long time (from 0.1 seconds, to even half hour) to complete
BackgroundWorker uses a ThreadPool thread to perform its processing. This means that closing your Application form will terminate the thread, since it's a background thread.
If your "half hour" processing "work" is something that you would like to have continue operating, even if the form is closed, you may want to make your own foreground thread to perform this operation, and handle the UI marshaling yourself.
While the BackgroundWorker object is an obvious choice, it may not be advisable for a lengthy process, as it uses the ThreadPool. The conventional wisdom around the ThreadPool is that it shouldn't be used for long-running tasks; in these cases explicit thread creation is advisable.
You can still interact with the GUI by calling Invoke or BeginInvoke on the form (or any of its controls), passing in a delegate that will perform the GUI-related actions.
If you have a very finite number of threads (let's say, at most 4), then you can create them yourself. If you need them to be managed in a way that you don't want to deal with it, then a threadpool is one option or .NET 4.0's System.Threading.Tasks namespace.
You'll probably need to use delegates. Here's an example of one that writes to the UI and one that reads from the UI:
delegate void SetResultsTextCallback(string text);
delegate string GetIterationCountCallback();
private void SetResultsText(string text)
{
if (this.ResultsBox.InvokeRequired)
{
var d = new SetResultsTextCallback(SetResultsText);
this.Invoke(d, new object[] { text });
}
else
{
this.ResultsBox.Text = text;
}
}
private string GetIterationCount()
{
if (this.RepetitionSelector.InvokeRequired)
{
var del = new GetIterationCountCallback(GetIterationCount);
IAsyncResult result = del.BeginInvoke(null, null);
return del.EndInvoke(result);
}
else
{
return RepetitionSelector.SelectedItem.ToString();
}
}
In this example, ResultsBox is a TextBox and RepetitionSelector is a combobox.
You have many options:
Use BackgroundWorker directly which basically does most of the work for you, but the lengthy operation must be known by the UI.
Inherit from System.ComponentModel.BackgroundWorker which enables to use the operation as a component and separate the logic from the UI.
Use the Event-based pattern, which would allow greater control for the parameters and events raised.
Use the delegates, if there is really nothing to report but the ned of the operation. You must have caution as the callback method is not guaranteed to run in the UI thread.
I recommend creating a thread and using a callback method to communicate with the UI.
I give an example in this solution, where you'll also find examples for other approaches: .NET Threading & Locks & Waiting.