In my application i am sending emails of bigger size (> 2.5 Mb). Now till the emails are being sent, the application is in hanged up state (mouse cursor is of busy state).
One of my friend suggested to use background worker that "could" display message something like "Please wait...Sending email". I have no idea as to how to use the background worker process. Please guide me
Or, if there is any other quicker/easier alternative, i would appreciate the inputs
You don't want to use a separate process - you want to use a different thread.
The work of sending the email shouldn't be done in the UI thread, as that will prevent it from updating. However, you may want to disable parts of your UI while the email is being sent, depending on your app.
When it comes to doing the email work in the background, you could create a new thread explicitly, use the thread pool, or create a BackgroundWorker. You probably want to use Control.Invoke or Control.BeginInvoke to marshal a delegate invocation back to the UI thread when the email has been sent. Personally I would probably use a thread directly for this - it sounds like it'll take a reasonable time, and my guess is that you won't be able to report meaningful progress (which is the main task that BackgroundWorker makes easy). EDIT: As per comments, BackgroundWorker also marshals exceptions to the UI thread, which you may find useful.
So something like:
public void SendEmailButtonClicked(object sender, EventArgs e)
{
// Make any changes to the UI here to disable whatever you want
new Thread(SendEmail).Start();
}
private void SendEmail()
{
// Do the sending of the email here (this is in the non-UI thread)
// Then afterwards, possibly in a finally block
Action action = EmailSent;
this.BeginInvoke(action);
}
private void EmailSent()
{
// Back in the UI thread, do whatever you need to indicate
// success/failure, re-enable disabled parts of the UI etc
}
The BackgroundWorker documentation contains some pretty good examples which should help to get you started.
A background worker is perfect for this. It allows you to monitor progress quite easily and can Marshall back to the UI thread easier than a standard thread. Some links after some google fu:
http://justins-fat-tire.blogspot.com/2010/05/c-using-background-worker.html
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://www.dotnetperls.com/backgroundworker
If you don't want your UI to hang while waiting for long processes you have to use a thread. BackgroundWorker is a good implementation of this that provides hooks for you to use to report progress, allow the user to abort the process etc.
There are plenty of questions about the BackgroundWorker here on Stack Overflow or check the MSDN documentation.
I would try to use BackgroundWorker control. Refer below links
Designing an Interface for BackgroundWorker
http://www.albahari.com/threading/part3.aspx
http://www.agiledeveloper.com/articles/BackgroundWorker.pdf
Look at this threading tutorial:
http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx
Basic idea is to have your mouse click event spawn a new thread that will take care of sending the email.
Related
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.
I have a multi threaded app where I have created a Producer/Consumer Pattern for the processing of XML files etc
What I want to know is what would be a good approach for updates to the UI and when the process finshed.
Should I go down a threaded approach and create Barrier and wait for all tasks to complete or should I just create an event/delegate and get the UI to catch this for both UI updates/compeltion
You may checkout Signalr which allows you to achieve PUSH notifications to clients.
Sorry, this answer was assuming Windows Forms, because there was no asp.net tag at first. Hopefully someone will provide a good answer for asp.net as well.
You can use Form.Invoke() to update stuff from the non-GUI thread, here's a simple example:
private void Form1_Load(object sender, EventArgs e)
{
Thread thread = new Thread(DoStuff);
thread.Start();
}
void DoStuff()
{
Thread.Sleep(1000);
this.Invoke(new Action(() => MessageBox.Show("Hey, this was invoked")));
}
With Invoke, you can do just about anything with the Form, it runs the invoked action in the form's thread. So you can change your status text or whatever that way. Of course, you shouldn't have your "business logic" inside the Form class, and you shouldn't use Thread.Sleep, I'm just showing the very basic fact that you can call back to the UI thread this way.
As to whether you should wait for all tasks to complete before doing anything, or show status updates as they execute, that's really up to you. I like to show updates on the UI when possible so the user knows what's going on. It's also good to have a progress bar going if there's something happening that the user might be waiting for. The progress bar can just be a marquee if you don't have a good way to indicate real progress.
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.
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.
I am using 3rd party library and some of the functions of the library take a long time to execute so I want to display a "Please Wait" dialog while the functions are busy.
Normally I would do something like this:
Thread longTask = new Thread (new ThreadStart(LongTask));
longTask.IsBackgroud = true;
longTask.Start();
pleaseWaitForm = new PleasWaitForm ("Please wait for task to complete");
pleaseWaitForm.ShowDialog();
void LongTask()
{
// Do time consuming work here
pleaseWaitForm.CanCloseFlag = true;
}
Unfortunately the 3rd party library is not thread-safe. Any workarounds? Is there any way of managing the Dialog Box as a background task?
I think you are misunderstanding what "thread safe" means. If you are going to be calling methods/properties of your 3rd party component only from single thread, the component does not have to be thread safe. See this article.
Furthermore, I would suggest you use a background worker class in this case.
HTH
You pretty much need to build your own dialog box.
One option is to poll your completed flag in a timer or the like.
Yet another option is to let the form "own" the task and use a BackgroundWorker for progress and completion notification.
Suppose you have a method, LongTask, and it is not thread safe. If that method is running and it does not need any shared variables, then you can simply wrap it around a BackgroundWorker and update the "please wait" screen the moment the task finishes.
If a certain method is not thread safe, that can still mean it is safe to use it in a thread, it just depends whether it runs multiple times asynchronously (danger!) or synchronously (not a problem).