I am using background worker to execute an "Import" web-service call;
This import operation call can take about 5 seconds to complete, so i was wondering how i could best visually entertain the user. I have seen that most progress bars are more or less used in loop operations where they get updated per object processed. In my doWorker, i just have the webservice call;
Something like :
Details importinfo = (Details)sender;
e.Result = WebService.ImportMe(importinfo);
So will it be smart to have a progress bar in such an operation or some animation while the user waits for completion ? How can i best approach this ?
When you have no idea how long it will take and/or at what "point" of the operation you are you can set the Style to ProgressBarStyle.Marquee.
Related
I'm a newbie in C#, and I'm going to develop a small program using a third party network library to send the requests.
Suppose there have some requests (just simple strings) stored in the queue qTasks, and it will handle those requests one by one with the order as submitted, the queue can be updated during execution, and it should be stopped whenever there has error returned.
I can just use a for loop to call the send request command in the array one by one, but unfortunately the sendrequest command is an async method with callback OnStageChanged, and I need to check the result before sending the next request when the status is "Done".
I'm now using the following method to handle it:
In the main UI Thread,
// Put those request text in a queue names qTasks, then call a goNextTask() to process the request one by one.
// The queue can be updated by the UI thread at anytime, goNextTask will be called periodically to handle those pending request in the queue.
private void goNextTask(bool lastSuccess = true)
{
if (lastSuccess)
{
if (qTasks.Count > 0)
{
// continue to next request
string requestText = qTasks.Dequeue();
SendRequest(requestText, OnStageChangeHandler);
} else {
// Report for all request sent successfully
}
} else {
// stop and show error
}
}
The callback method OnStageChangeHandler will be called by the library whenever the stage changes, and it will have state "Done" when completed.
private void OnStageChangeHandler(object sender, StageChangeEventArgs e)
{
if (e.newState == SessionStates.Done)
{
// check result here
bool success = <...>
// then call the goNextTask in UI thread with the result of current request.
Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
(Action)(() => goNextTask(success)));
}
}
Although it works fine now, I think it's a little bit stupid as it has a somewhat recursive flow (A -> B -> A -> B ->....).
I learnt that MS has improved the web request handling, so that it can work in sync mode.
I'd like to know if I can have a wrapper to make the above async call work as a sync call, so that it can be done in a simple flow as a loop like that:
while (qTaks.Count > 0)
{
if (!sendAndWaitReturn(qTasks.Dequeue())) {
// Report error and quit
}
}
// all tasks completed
This sendAndWaitReturn method will send the request, then wait for the status "Done", and then return the result.
I found some example that may use a control flag to indicate the status of the current request, and the callback function will update this control flag, while the UI thread will loop on this flag using a while loop:
while (!requestDone);
so that it will not continue to nextRequest until requestDone. But in this case, the UI will be blocked.
Is there any better way to convert the async call to work as a sync call without blocking the UI thread?
The difficulty you're going to run into is you have conflicting desires. On one hand, you want to avoid blocking the UI thread. On the other hand, you don't want to run things asynchronously and so you're going to block the UI thread.
You're going to have to pick one, and there's absolutely no reason to keep on doing things synchronously (especially in light of blocking the UI thread). If it hurts when you do that, don't do that.
You haven't specified, but I'm guessing that you're starting this processing from a button click event. Make the method invoked by that click event async. For example:
private async void StartProcessing_Click(object sender, EventArgs e)
{
await Task.Run(() => StartProcessing());
}
There, you've started processing and the UI thread isn't tied up.
The next thing is that, you're right, having the event behave in that cyclical manner is silly. The event is to notify someone that the state has changed, its goal isn't to manage queue policy. The queue should manage queue policy (or if you'd rather not abstract that out, the method that processes requests).
So how would you do that? Well, you've said that SendRequest hands the session object back to the caller. The caller is presumably the one who is orchestrating queue policy and determining whether or not to call SendRequest again.
Have the caller check the session object for validity and decide whether to keep going based on that.
Additionally, I'm unfamiliar with that particular library, but briefly glancing at the documentation it looks like there's also a SendRequestAndWait() method with the same signature and that sounds like it might better meet your needs.
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.
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.
I have read that I can use asynchronous call with polling especially when the caller thread serves the GUI. I cannot see how because:
while(AsyncResult_.IsCompleted==false) //this stops the GUI thread
{
}
So how it come it should be good for this purpose? I needed to update my GUI status bar everytime deamon thread did some progress..
You are correct in your while loop stopping the GUI thread, when doing it like that, you don't want to do that.
If you need to poll, it would be better is to set up a Timer, and check whether the work has completed when the timer fires. The Timer can have a small resolution without problems (100 ms for instance), as long as you dont do much work during each tick.
However, I think you would be even better off by using a callback, so you do not need to poll and get notified as soon as your workload is done.
The point of async polling is that you can do other things in between checking IsCompleted — such as servicing GUI events. You could set a timer, for example, to trigger an event several times per second to check whether your asynchronous operation is finished, and use the normal GUI event loop to service those events together with all the other events your GUI receives. That way, your GUI remains responsive, and shortly after the async operation finishes, your timer event handler will notice it.
I was having the same trouble with an old API exposing BeginExecute() and EndExecute(). BeginExecute() started asynchrounous operation and then went silent until it finished executing to the end. But I was needed to update intermediate state of the execution progress in real-time.
So I came up with the following solution:
var asyncResult = command.BeginExecute();
while (!asyncResult.IsCompleted)
{
if (command.State != OldState)
{
progress.Report(newState);
}
// Key piece in this polling loop.
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
}
command.EndExecute(asyncResult);
At first I have used
await Task.Yield();
But then I found out that in WPF it won't return the control to GUI, because this loop will have higher priority. That is why I switched to this instruction:
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
So now GUI will check and update progress only when it has nothing else to do :)
I'm writing a plug-in for another program which uses the native program to open a series of files to extract some data from. One problem I am having is the process takes a long time and I want to keep the user interface from hanging. Plus I also want to give the user the ability to cancel the process before it completes. In the past I've used a background worker for this type of thing, but in this case I don't think a BackgroundWorker will work.
To create a plug-in through the API I am using one can create a custom command by inheriting from an IAPICommand interface. This interface includes an Execute(Application app) method. The class is then instantiated and the Execute() method is called by the program when the user evokes the custom command in the program.
The Execute() method is passed a reference to the current Application object when it is called, and it is this application object that is used to open the files to extract data from. However, the application instance is not able to open a document when requested by a thread other the the original Execute() thread.
So typically the UI would exist on the main thread, and the time consuming data extraction would be performed on a secondary thread. However, in this case the data extraction must be performed on the main thread, and I need to create a secondary thread for the UI.
Here's a stripped down version of the code.
class MyCommand:IAPICommand
{
public void Execute(Application app) // method from IAPICommand
{
Thread threadTwo= new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
}
//method to open custom form on a seperatethread
public void ShowFormMethod()
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
Here is a flow chart that shows how I think this should ultimately work.
alt text http://dl.dropbox.com/u/113068/SOMLibThreadingDiagram.jpg
Does this diagram make any sense, and if so am I even taking the correct approach to solve this problem?
Once the main thread starts the UI thread I want it to wait for the user to either select widgets to process, or end the command by closing the form (the red figures on the diagram). How can I make the main thread wait, and how do I trigger it to continue either with processing or to continue to the end when the UI thread ends? I was thinking I could have the main thread wait on a Monitor lock. The UI thread would then populate a static list of Widgets to be processed, and then pulse the main thread to trigger the processing. The UI thread would also pulse the Main thread when the form is closed, and the main thread would know to continue to the end of the command if it was ever pulsed when the list of widgets to process was empty.
How do I allow the main thread to communicate the progress or completion of widget processing back to the UI thread (yellow arrows in the diagram)? Do I just used the BeginInvoke() method of the Form to do this?
How do I allow the UI thread to cancel the widget processing (green arrow in the diagram)? I think I could just setup a static Boolean flag that is checked before each widget is processed?
It's generally a bad idea to have multiple threads in your application that each create forms. It isn't impossible to make this work, but it's much harder than you think it will be because forms that are in a parent-child relationship send messages to each other, and when they do, the one sending the message blocks until the one receiving handles it.
Mix this in with the message passing or synchronization between threads that you are doing explicitly, and it's easy to end up with deadlocks. So, in general, you are better off making sure that you reserve your main thread for your user interface, and do all processing in other threads that have no UI.
If you conform to that design, then the background threads can use Control.BeginInvoke to pass messages to the UI thread without having to wait for the messages to be processed.
In addition to the other answers, I recommend that you use a callback method from ProcessWidget to pass progress back to the calling thread. To prematurely stop the worker thread, you can use the callback to return a halt signal to your worker thread if it updates the caller often enough. Or use a separate callback method to periodically check for go/no-go. Or set a (gasp!) global static flag that the worker periodically checks. Or call Thread.Abort on the worker thread and have it catch the ThreadAbortException to clean up any resources.
I assume that the host application is a WinForms app.
You need to save the SynchronizationContext from the original thread in your Execute method, then call its Send method to execute code on the host's UI thread.
For example:
class MyCommand:IAPICommand
{
SynchronzationContext hostContext;
public void Execute(Application app) // method from IAPICommand
{
hostContext = SynchronzationContext.Current;
Thread threadTwo = new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
SomeType someData = null;
hostContext.Send(delegate { someData = app.SomeMethod(); }, null);
}
}
If you look at Java swing, it is a nice example of how to do this:
1) A main thread is responsible for handling all UI requests. This removes any race conditions from the app.
2) Any time any "work" is to be done, spawn a thread (or a thread pool) and do the work. Thus the main thread is not held up except for a few microseconds and the UI is completely responsive while whatever is going on.
3) In all languages there has to be a thread interrupt mechanism. In java you invoke .interrupt() on the thread, and the current running thread gets a InterruptedException thrown wherever it is executing. You job is to catch that exception, figure out if you are really interrupted (read javadocs for this part) and if you are just let yourself die (return out of the run method).
1 + 2 = unobtrusive client interaction
3 = killing threads
An alternative to 3 (if 3 is too complex) is to give the thread a method .kill(); the method sets a kill flag. When you are reading a buffer from the hard drive in a loop, check if the kill flag is set, if it is then break out of the loop, close handlers, and return out of the run method.
Edit: sorry forgot to mention progress report:
Your thread should have a publicly exposed thread-safe method of getting the "progress report" or rather a data structure containing information about progress. Your UI thread should periodically (say every .5 seconds) check the thread's progress report and update the UI's progress bar. And by UI thread checking I mean your widget that shows the progress makes a request to re-render with the latest information on a timer, until done.