What's the difference between Window.BeginInvoke() and Control.BeginInvoke()? - c#

I need to change the Label Content. but The code will sleep before execute it. So what's the different I use window execute the code or use control itself? like:
// Use Label execute
Label1.BeginInvoke(new Action(()=>{
System.Thread.Thread.Sleep(5000);
Label1.Content = "New Value";
});
// Use Window execute
MainWindow.BeginInvoke(new Action(()=>{
System.Thread.Thread.Sleep(5000);
Label1.Content = "New Value";
});
No matter I use Label or Window, it always stuck the UI when the Thread sleep. Why? Why it just don't freeze the label when we execute Label.BeginInvoke() , If Is there no any different, Why Microsoft not remove the Mothod for Control.Begininvoke()
Update1:
Sorry for the Sleep(5000), I just let you know there is a method will take a lot time for execute before change the Label Content.
Update2
So If there is no any different, Then no different with Control2.BeginInvoke() and Control3.BeginInvoke() ?
Then Why Microsoft just don't keep only the Window.Begininvoke()?
Update3
Why I can change the Control2.Content in Control3.BeginInvoke? If there is no limit Why All has that method? what for?
Update4
Maybe the Update2-3 is dummy qustion, sorry for that, what I mean is : If we can change the label1.content in windows.begininvoke(), why we still need label1.begininvoke()?

From the documentation of Control.BeginInvoke
Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.
The documentation of Thread.Sleep
Suspends the current thread for the specified amount of time.
Both the Window and the Label were created on the same thread (the UI thread). When you call Thread.Sleep() on that thread (using BeginInvoke) it does exactly what you would expect it to and causes the thread to get suspended (this thread is responsible for listening to windows messages and keeping the UI "responsive" which is why your application freezes)
I noticed that in one of your comments you wrote
#alykins, Because That mean there is some method will take alot time, and I don't let the main UI thread stuck in there.
The solution to this problem is not to call Sleep on the UI thread. You need to hand off the long running task to a separate worker thread and not do it on the UI thread. Consider reading up on the Task Parallel Library for one way to do this.
Answer to your latest update
If we can change the label1.content in windows.begininvoke(), why we still need label1.begininvoke()?
In the unlikely scenario that your Label and Window were created and owned by separate threads (and not the UI thread), you would use Label.BeginInvoke() to update the Label and Window.BeginInvoke() would not work`.

Related

How to call Same event Handler with multiple class object in Windows form C# [duplicate]

I have a windows forms application
on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,
and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?
You need to perform the long running operation on a background thread.
There are several ways of doing this.
You can queue the method call for execution on a thread pool thread (See here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
In .NET 4.0 you can use the TaskFactory:
Task.Factory.StartNew(() => YourMethod());
And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():
Task.Run(() => YourMethod());
You could use a BackgroundWorker for more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.
Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Thread class if you want to learn about this.
Remember that with anything threaded, you cannot update the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.
private voidForm_Load(object sender, EventArgs e)
{
MethodInvoker mk = delegate
{
//your job
};
mk.BeginInvoke(callbackfunction, null);
}
private void callbackfunction(IAsyncResult res)
{
// it will be called when your job finishes.
}
use MethodInvoker is the easiest way.
Obviously, you need to use background threads. I suggest you read this free e-book.

c# downloadfileasync wait without freezing ui

The problem is very simple, yet I haven't found any specific article.
I want to be able to download a file async, wait until it completes, show a progress bar, but then continue from the point where I was in the main thread, and NOT from the filecompleted raised event. I need the file download to be async because I need to show a progress bar. And I'm forced to use .NET 2.0.
All the pages I found are solving this problem simply running the DownloadFileAsync as the last command, so there's nothing more to run... this way is simple, because the execution "continues" when the downloadfilecompleted triggers. All, all, all the samples I searched are working this way.
But what I need is to remain on the main thread, wait, let the downloadprogresschanged access the UI to update a progressbar, and then continue from there.
Something like this:
private ManualResetEvent myMREDown = new ManualResetEvent(false);
WebClient myClient = new WebClient();
myClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(myClient_DownloadProgressChanged);
myClient.DownloadFileCompleted += new AsyncCompletedEventHandler(myClient_DownloadFileCompleted);
myClient.DownloadFileAsync(SomeURL);
mre_DownloadingFile.WaitOne();
ContinueDoingSomethingElse(); // <-- I want to reach THIS point after download
void myClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
//update the progress bar
}
void myClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
mre_DownloadingFile.Set();
}
Now, my questions are:
A) Generally speaking, if I just run DownloadFileAsync, I understand the download happens in a separate thread, because if I write some more code after that, it will be run without waiting for the DownloadFileAsync to complete... however, if I WaitOne() from my main thread, that download thread seems to hung, because it doesn't shows any progress bar... So... it's on a separate thread from mine or not ???
B) If I wrap the entire download process into a method and then I use Start New Thread() to run it, and after that I use a ManualResetEvent Waitone(), the UI freezes the same...
C) Most of all... is there a wayout ???? (please providing code too, if possibile)
Ok I went deep on the problem and so I'll reply to myself, I hope this will help someone else with my same doubts.
Answers:
A) Generally speaking, if I just run DownloadFileAsync, I understand
the download happens in a separate thread, because if I write some
more code after that, it will be run without waiting for the
DownloadFileAsync to complete... however, if I WaitOne() from my main
thread, that download thread seems to hung, because it doesn't shows
any progress bar... So... it's on a separate thread from mine or not
???
The problem is: you can't wait on the main UI thread. That means that when you run the program, it normally runs on a thread that is the one that has access to the UI. So, no matter what you do and how, if you WaitOne() there, your UI will freeze. No wayout to this. Keep it as it is.
When you run the DownloadFileAsync it SPAWNS a new thread, but since from there you are trying to update a progress bar that is on the main thread, if that thread is waiting, it will not be able to do anything. So the problem is, again, you can't wait on the main thread.
B) If I wrap the entire download process into a method and then I use
Start New Thread() to run it, and after that I use a ManualResetEvent
Waitone(), the UI freezes the same...
The reason is the same of point A) - even if you start a new thread, but then you wait on the main thread UI, you'll not be able to go anywhere.
C) Most of all... is there a wayout ???? (please providing code too,
if possibile)
Yes, the solution is: think your program differently. Since you can't wait there, you need to recode everything so that you must be able to run the asyncdownload, abandon the program logic you were doing until then, and continue it elsewhere (from the DownloadFileCompleted event in my case). You could for example run everything on a new thread, update the progress bar using delegates (so they'll call UI updates from the right thread), and then from this new thread you'll be able even to Wait(), because this will put the waiting on a separate thread, that is not the main one.
In my case, I had a list of commands to execute... so I first created a Queue and added all commands there, then I created a method "RunNextCommand" that dequeues the Element and runs the command, and if one of the commands is "downloadafile", then I just run the asyncdownload, and run one more "RunNextCommand" from the DownloadFileCompleted event.
This way you don't use DoEvents() (that is always a very bad idea), your CPU doesn't runs 100%, and your code is beautiful and clean ;-)
Thank you to myself. I'm welcome. Bye.

How to retrieve information in a second thread with a Windows Forms C# Application

I have an usual C# Windows Forms Application with one Form and several TextBoxes / Labels which runs (how I understand) in its own thread. (Win 7 64 / VS 2008 / Net 2).
Now I want to start a second thread while my base application stays in the first thread.
The second thread shall retrieve some system information and input it into the Labels while my user is still able to fill in the TextBoxes while the information is going to be retrieved by the second thread. So the advantage would be by my understanding, that the user has not to wait until retrieving information is completed and the main application would not hang in that time.
Let's say I want this code to be executed in a second thread which starts in the Form_Shown event:
Label1.Text = GetInternetIP();
try
{
Label2.Text = System.Net.Dns.GetHostEntry(Label1.Text).HostName.ToString();
}
catch{MessageBox.Show("Fatal Error."); Process.Start("shutdown.exe", "-r -t 2"); this.Activate(); SendKeys.Send("%{F4}");}
I would be grateful for a detailed description on how to setup a "new thread". I am a newbie but I would like to learn something new and optimize (speed up) my very first applications.
The Label1 and Label2 are in the main thread on the main form (Form1). So I have to get the retrieved information there.
in dealing with Windows forms the UI can only run on one thread, then it will create background threads the background threads retrieve the data and then pass it to the single UI Thread. This is also how it works in WPF.
take a look here on how to do this
http://msdn.microsoft.com/en-us/magazine/cc300429.aspx
You should never access your UI components from code running on another thread. In fact, you shouldn't access anything from multiple threads unless those things are explicitly thread-safe (or you access them in a thread-safe manner).
In your example you are saying you want to fetch information which takes some time. In your case the programming model you want is to have your main thread call an asynchronous function to retrieve that information, and it should signal your main thread when the information is ready.
There are a lot of different ways to implement multithreaded programming in C#, but here is one example:
public Task<IPAddress> GetInternetIP()
{
return Task.Factory.StartNew(() =>
{
IPAddress ip;
// do some work to get the IPAddress
return ip;
});
}
private void Form_Load(object sender, EventArgs e)
{
GetInternetIP().ContinueWith(ip =>
{
Label1.Text = ip.ToString();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
In this case what you're doing is executing a System.Threading.Tasks.Task which will handle the multithreading for you. And you're telling it to continue execution with a method on the current thread. That method is passed the return value of the task (in this case an IPAddress object).
to access user controls that are on the main thread from your background thread you only need to use BeginInvoke against the controls you want to populate. This is an article that fully explains how to do so along with the ins and outs of doing so.
http://weblogs.asp.net/justin_rogers/pages/126345.aspx
The three answers which I received brought me nowhere or have not worked, so I found it out myself much later: I used the Backgroundworker-Control to achieve what I wanted. In the "Completed"-Event of the Backgroundworker I can access the UI and transfer the information to the form attached to my application. What helps me a second thread if my UI is locked for that second thread, so Backgroundworker is the best for me to go and self-explaining.

C# Thread Pool Cross-Thread Communication

The Scenario
I have a windows forms application containing a MAINFORM with a listbox on it. The MAINFORM also has a THREAD POOL that creates new threads and fires them off to do lots of different bits of processing. Whilst each of these different worker threads is doing its job, I want to report this progress back to my MAINFORM, however, I can't because it requires Cross-Thread communication.
Progress
So far all of the tutorials etc. that I have seen relating to this topic involve custom(ish) threading implementations, whereas I literally have a fairly basic(ish) standard THREAD POOL implementation. Since I don't want to really modify any of my code (since the application runs like a beast with no quarms) - I'm after some advice as to how I can go about doing this cross-thread communication. ALTERNATIVELY - How to implement a different "LOGTOSCREEN" method altogether (obviously still bearing in mind the cross-thread communication thing).
WARNING:
I use this website at work, where we are locked down to IE6 only, and the javascript thus fails, meaning I cannot click accept on any answers during work, and thus my acceptance rate is low. I can't do anything about it I'm afraid, sorry.
EDIT:
I DO NOT HAVE INSTALL RIGHTS ON MY COMPUTER AT WORK.
I do have firefox but the proxy at work fails when using this site on firefox.
And no, funnily enough, I don't have the internet at home, I literally just moved to this city and the flat is a new build, so the address hasn't been registered with the post office, and thus the phone company cannot find the address on their system till they send a surveyor out, smarty pants.
FURTHER EDIT:
I DO NOT WANT TO CHANGE MY THREADING IMPLEMENTATION. AT ALL! - Accept to enable cross-thread communication....why would a backgroundworker help here!?
CODE RELATED EDIT:
Does it make a difference that when my THREAD POOL executes the new threads, it creates a new instance of a class and calls the entire thing on that new thread........i.e. your code example doesn't quite fit....i think?
Use the BackgroundWorker class in .NET and use the ProgressChanged and RunWorkerCompleted events to communicate back to your UI thread
Edit:
Sounds like you don't like BackgroundWorker, or just don't want to refactor. In that case, you have to check the InvokeRequired property on your form or one of your controls and if it is true, then you have to call Control.Invoke to force your UI update logic to occur on your main thread.
here is an example:
private void MyThreadFunction()
{
if (!InvokeRequired)
{
myLabel.Text = "You pushed the button!";
}
else
{
Invoke(new ThreadStart(MyThreadFunction));
}
}
You can use any delegate type to pass to Invoke, because it takes optional parameters that can be passed to your delegate when it is invoked on the main thread.
You could do something like this:
class MyForm : Form
{
private Label label = new Label();
private void DoWork()
{
// Do work ... Not in UI thread
// Update label... In UI thread
this.Invoke(new MethodInvoker(() => label.Text = "New Text!"));
}
}
The DoWork method it's the one running in your worker threads. You could check if an invoke is required using InvokeRequired property, but the assumption is that your code is running on worker threads so the invoke will always be required.
You can do this using delegate object.
So you would create a callback method in your MAIN form and let your CHILD forms call this method using delegates when they are done processing.
Try using Control.BeginInvoke to queue your update to the UI on the UI thread.

WinForm Application UI Hangs during Long-Running Operation

I have a windows forms application
on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,
and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?
You need to perform the long running operation on a background thread.
There are several ways of doing this.
You can queue the method call for execution on a thread pool thread (See here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
In .NET 4.0 you can use the TaskFactory:
Task.Factory.StartNew(() => YourMethod());
And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():
Task.Run(() => YourMethod());
You could use a BackgroundWorker for more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.
Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Thread class if you want to learn about this.
Remember that with anything threaded, you cannot update the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.
private voidForm_Load(object sender, EventArgs e)
{
MethodInvoker mk = delegate
{
//your job
};
mk.BeginInvoke(callbackfunction, null);
}
private void callbackfunction(IAsyncResult res)
{
// it will be called when your job finishes.
}
use MethodInvoker is the easiest way.
Obviously, you need to use background threads. I suggest you read this free e-book.

Categories

Resources