Display "Busy Indicator" using background thread - c#

I am doing some heavy computations on the main thread and these computations cannot run on a separate thread.
I want to display a "Busy Indicator" (i.e., spinning widget) on the application UI when these computations are running. As such, I cannot show the busy indicator on main thread as the UI is locked while these computations are running.
To work around this issue, I tried to move the busy indicator to separate thread. With the help of this post I am able to place the busy indicator on separate thread. However, I am not able to communicate with this thread to start or stop the busy indicator.
private HostVisual CreateBusyIndicatorOnWorkerThread()
{
// Create the HostVisual that will "contain" the VisualTarget
// on the worker thread.
HostVisual hostVisual = new HostVisual();
Thread thread = new Thread(new ParameterizedThreadStart(BusyIndicatorWorkerThread));
thread.ApartmentState = ApartmentState.STA;
thread.IsBackground = true;
thread.Start(hostVisual);
// Wait for the worker thread to spin up and create the VisualTarget.
s_event.WaitOne();
return hostVisual;
}
private static AutoResetEvent s_event = new AutoResetEvent(false);
private void BusyIndicatorWorkerThread(object arg)
{
// Create the VisualTargetPresentationSource and then signal the
// calling thread, so that it can continue without waiting for us.
HostVisual hostVisual = (HostVisual)arg;
VisualTargetPresentationSource visualTargetPS = new VisualTargetPresentationSource(hostVisual);
s_event.Set();
// Create a MediaElement and use it as the root visual for the
// VisualTarget.
visualTargetPS.RootVisual = CreateBusyIndicator();
// Run a dispatcher for this worker thread. This is the central
// processing loop for WPF.
System.Windows.Threading.Dispatcher.Run();
}
private FrameworkElement CreateBusyIndicator()
{
var busyIndicator = new MyBusyIndicator();
//busyIndicator.DataContext = this.
Binding myBinding = new Binding("IsBusy");
myBinding.Source = this;
busyIndicator.SetBinding(MyBusyIndicator.IsBusyProperty, myBinding);
}
I always gets an exception "The calling thread cannot access this object because a different thread owns it". This is because I am trying to update the busy indicator from the main thread while the busy indicator is owned by a different thread.
I have also tried an approach given in this article,
private void CreateAndShowContent()
{
Dispatcher = Dispatcher.CurrentDispatcher;
VisualTargetPresentationSource source =
new VisualTargetPresentationSource(_hostVisual);
_sync.Set();
source.RootVisual = _createContent();
DesiredSize = source.DesiredSize;
_invalidateMeasure();
Dispatcher.Run();
source.Dispose();
}
But with this approach Dispatcher.Run() nothing happens until after the completion of the computations and then the busy indicator is displayed.
I want to communicate from main thread to the thread having busy indicator. Does anyone have an approach?

There is no reason to run "heavy computations" in UI thread. Even more - this is a bad practice. Instead use BackgroundWorker which will do work, meantime alive UI-thread will show Loading/Calculating:
var worker = new BackgroundWorker();
worker.DoWork += (s, e) => {
// This part will last at a separate thread without blocking UI.
// Excellent place for heavy computations.
}
worker.RunWorkerCompleted += (s, e) => {
// Here we're back to UI thread - so you can change states and stop animations.
}
// And finally start async computation
worker.RunWorkerAsync();
UI should contain BusyIndicator control which will be activated/stopped when you'll start/finish worker.

Please stop what you are doing... it is totally incorrect. #Anatolii Gabuza was correct... you shouldn't do any long running process using the UI thread as this will block it, making the application unusable at these times. Unless your long running process is rendering UI objects, then there really is no reason to do it using the UI thread... let us know what it is and we can help you to run it on a background thread correctly.
So you discovered that you can't display your busy indicator on the UI thread because it is busy with your long running process... at this point, most developers would realise their error, but unfortunately, not you. Instead of accepting that the long running process should be run on a background thread, you do the exact opposite and now want to display some UI element in a background thread, while blocking the UI thread with a long running process???
This is utter madness, if you want to avoid some horrendous problems, please stop. If you continue, then you'd better get used to seeing that exception:
The calling thread cannot access this object because a different thread owns it.

You need to invoke it busyContainer dispatcher. use as below
this.busyContainer.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
//update busy Container
}));

I got this from SO but cannot find it on SO
Run this on the UI thread and put in your task where very long task is
public class WaitCursor : IDisposable
{
private Cursor _previousCursor;
public WaitCursor()
{
_previousCursor = Mouse.OverrideCursor;
Mouse.OverrideCursor = Cursors.Wait;
}
#region IDisposable Members
public void Dispose()
{
Mouse.OverrideCursor = _previousCursor;
}
#endregion
}
using (new WaitCursor())
{
// very long task
}

Related

Waiting for Dispatcher.Invoke in WPF UI thread

I've got a BackgroundWorker that occasionally needs to call into the UI thread to perform some work and retrieve a result. To achieve this I'm using the following from within the background thread:
App.Current.Dispatcher.Invoke(new Action(() => { /* some code that updates local data */ });
As the app is exiting, I want to be able to tell the BackgroundWorker to quit but I want to allow it to finish any current operations. In other words, I want to call BackgroundWorkerObj.CancelAsync() and then pump messages until the thread has exited.
I've tried the following, but the Invoke() in the background thread still blocks (though the UI thread is still churning):
Worker.CancelAsync();
while (Worker.IsBusy)
{
DispatcherFrame Frame = new DispatcherFrame();
Frame.Continue = false;
Dispatcher.PushFrame(Frame);
}
What's the correct way to do this? How can the UI thread wait on the BackgroundWorker while still executing Invokes from that BackgroundWorker object?
This sort of shutdown deadlock is exactly why you shouldn't use Invoke for this purpose.
Change it to BeginInvoke(), and for communications back to the worker thread use an event.
I would use Task.Run since you're on .NET 4.0. but anyways. You have to do it the other way around. Wait for the backgroundworker to finish and then exit the application. There is no way to wait for the background thread to finish in an closing event while keeping the main thread responsive. This while loop will block the main thread and message pump until the background thread is done.
Try this
private BackgroundWorker _worker;
protected override OnFormClosing( object sender , FormClosingEventArgs e )
{
base.OnFormClosing( sender , e );
// Cancel's the closing and keeps the form alive
e.Cancel = _worker.IsBusy;
}
private void RunWorkerCompleted( object sender , RunWorkerCompletedEventArgs e)
{
// Work is done, so close the form
Close();
}

uses of creating a thread and Blocking UI

I have started a special course in multithreading but I have some fundamental issues I want to clear up. say I have a thread
Thread t1 = new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
IsCancel = false;
this.workProj.DoWorkWithRefSync(ref IsCancel);
});
t1.Start();
Followed by
while(t1.IsAlive)
{
}
or
t1.Join();
or
myAutoResetEvent.WaitOne(); // myAutoResetEvent.Set() called in thread when it finished processing
I am not sure but, this might not be a good example but looking forward to one.
I know that they are all some form of signaling from the background thread to inform the calling/UI thread that the work has completed.
But using them end up blocking the UI until the thread completes. So I would like to know a real life scenario implementation of this.
I am thinking why not just run this process on the UI thread since you don't mind blocking it.
Edit: In otherwords, I am looking for the real uses of these blocking elements such as thread.Join() etc
A real life scenario relevant to your example would be where the reference to the thread is stored in a member of the window class, and it gets checked or waited for if some event triggers such as closing the window or the application exiting.
pseudo code:
class Window
{
private Thread _thread = null;
public void OnButtonClick()
{
_thread = CreateAndStartThread();
}
public void OnCloseWindow()
{
if(null != _thread)
_thread.Wait();
}
}

C# worker thread with event driven work and no shut down

Here's what I woulld like to do:
Create a worker thread in my main thread (which controls the UI).
The worker thread keeps running until shut down by the main thread (which only happens when the entire application is shut down).
The main thread listens for keyup, but sends an event to the worker thread to process the keyup asynchronously (to avoid blocking the UI).
The worker thread updates the UI when the keyup has been handled.
So far I've just been creating a new thread every time there is a keyup, but it seems there is just too much overhead this way.
As far as I can tell, I should use the BackgroundWorker class, but the examples I've seen seems to start a background worker, continue with non-blocked UI in the main thread and update UI from the BackgroundWorker when it's finished - i.e. exactly the same as I'm already doing.
How to make it so the worker thread keeps running and sleep when there is no work to be done?
While Zaches answer is completely valid (and an approach I used for some time) I've stumbled upon what I think is a more elegant solution using Dispatcher:
Create the worker thread:
Dispatcher _workerDispatcher;
Thread _workerThread = new Thread(new ThreadStart(() =>
{
_workerDispatcher = Dispatcher.CurrentDispatcher; // Required to create the dispatcher
Dispatcher.Run(); // Keeps thread alive and creates a queue for work
});
_workerThread.Start();
Put work into the worker thread (from main thread or another thread):
// Synchronous work
_workerDispatcher.Invoke(() =>
{
// Do stuff
});
// Asynchronous work (makes most sense for background work)
_workerDispatcher.BeginInvoke(() =>
{
// Do stuff
});
Shut down the worker thread:
_workerDispatcher.InvokeShutdown();
_workerThread.Join(); // Wait for thread to shut down
I'm using new Thread() because I need to set apartment state, but you can also use tasks created using Task.Run() and Task.Factory.StartNew().
I'm not 100% certain that it's necessary to call thread.Join(), but I'd rather be certain that the thread has been shut down. If you're using a Task call task.Wait() instead.
Another way to get the Dispatcher is to call Dispatcher.FromThread(thread), but it's important to note that a Dispatcher is NOT created until CurrentDispatcher has been used (even if you don't use the reference later).
A downside of this approach is that it can't be used to have multiple threads pick items out of a queue and do work - for that you will have to use the producer/consumer approached described in Zaches answer. The dispatcher approach allows you to queue up work in a specific thead.
Why don't you just use the Task Parallel Library?
Create a new task whenever you detect the KeyUp event, and let TPL worry about creating new threads. Since it uses the thread pool, a new thread will not be created every time an event is fired.
The problem you are having is called the Producer/Consumer problem. And you can solve it easily using any of the ConcurrentCollections available.
Try something like this:
var queue = new ConcurrentQueue<string>();
var consume = true;
var producer = Task.Run(() =>
{
var input = Console.ReadLine();
while(!string.IsNullOrEmpty(input)
{
queue.Enqueue(input);
input = Console.ReadLine();
}
});
var consumer = Task.Run(() =>
{
while(consume) //So we can stop the consumer
{
while(!queue.IsEmpty) //So we empty the queue before stopping
{
stringres;
if(queue.TryDequeue(out res)) Console.WriteLine(res);
}
}
});
await producer;
consume = false;
await consumer;
Try using the Task Pattern Library instead of manually starting up threads. It is your friend.

Need help with threading -C# Windows Forms

I am trying to create a thread that contains a form progress bar (just a GIF image).
I have called StartProgress() right before a large method. Basically when the thread starts it loads up the ProgressBar form (which I want to show all the time, and just hide it when it's not needed) and with ProgressActive set to true, it should display the form until ProgressActive is false, then the form should be hidden (until progress is active again). Here is what I have so far, but it freezes up on me :(
public static string ProgressInfo="Test";
public static bool ProgressActive=true;
public static bool ThreadStarted = false;
public static void StartProgress()
{
while (!ThreadStarted)
{
Thread t = new Thread(new ThreadStart(Progress));
ThreadStarted = true;
t.Start();
}
}
public static void Progress()
{
while (ThreadStarted)
{
LoadingBar lb = new LoadingBar();
lb.Show();
lb.TopMost = true;
while (ThreadStarted)
{
if (ProgressActive)
{
lb.Visible = true;
lb.lblLoadingStatus.Text = ProgressInfo;
}
else
{
lb.Visible = false;
}
Thread.Sleep(1000);
}
}
}
EDIT: I am trying to do this within a static class.
Is there any reason for not using BackgroundWorker if using .NET 2.0 or higher?
The reason I am saying that is because BackgroundWorker is event based, so it exposes an event like ProgressChanged which can reduce the overall size of your code.
The freezing is due to the fact you are trying to change your progress bar contained on the UI thread from your worker thread. I would recommend raising an event from within your worker Progress function to a handler on the UI thread. You will need to marshall the call to the handler on the thread as below.
private object _lock = new object(); //should have class scope
private void ShowProgressControl(EventArgs e)
{
if (this.InvokeRequired)
{
lock (_lock)
{
EventHandler d = new EventHandler(ShowProgressControl);
this.Invoke(d, new object[] { e });
return;
}
}
else
{
//Show your progress bar.
}
}
Enjoy!
The problem is that you need a message loop for any UI element to work correctly. Since you are creating the form in a worker thread then there is no message loop running. To create the message loop you have to call Application.Run or Form.ShowDialog both of which are blocking calls. Obviously that solution would hang up your worker thread.
The best thing to do is to create a separate thread dedicated to running the message loop and which can safely handle forms and controls. Have the worker thread periodically publish progress information to a variable that can be shared between the worker thread and the UI thread. Then have the UI thread periodically poll (using System.Windows.Form.Timer) that shared variable and update the UI accordingly.
As a side note, I would avoid using Control.Invoke or Control.BeginInvoke to push the progress information to the UI thread. You situation seems to warrant the polling approach instead. The reasons for preferring polling over pushing are:
It breaks the tight coupling between the UI and worker threads that Control.Invoke imposes.
It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.
The UI thread gets to dictate when and how often the update should take place.
There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.
The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).
You should create the progress bar on the main thread.
Make sure your heavy procedure runs from another thread.

In C#, wait on the mainthread while continuing to process UI updates? (.NET 2.0 CF)

I want to otherwise block code execution on the main thread while still allowing UI changes to be displayed.
I tried to come up with a simplified example version of what I'm trying to do; and this is the best I could come up with. Obviously it doesn't demonstrate the behavior I'm wanting or I wouldn't be posting the question. I just hope it gives some code context to back my poor explanation of the problem I'm hoping to solve.
Within a button click handler on a form I have this:
private void button2_Click(object sender, EventArgs e)
{
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
new Thread(delegate()
{
// do something that takes a while.
Thread.Sleep(1000);
// Update UI w/BeginInvoke
this.BeginInvoke(new ThreadStart(
delegate() {
this.Text = "Working... 1";
this.Refresh();
Thread.Sleep(1000); // gimme a chance to see the new text
}));
// do something else that takes a while.
Thread.Sleep(1000);
// Update UI w/Invoke
this.Invoke(new ThreadStart(
delegate() {
this.Text = "Working... 2";
this.Refresh();
Thread.Sleep(1000); // gimme a chance to see the new text
}));
// do something else that takes a while.
Thread.Sleep(1000);
autoResetEvent.Set();
}).Start();
// I want the UI to update during this 4 seconds, even though I'm
// blocking the mainthread
if (autoResetEvent.WaitOne(4000, false))
{
this.Text = "Event Signalled";
}
else
{
this.Text = "Event Wait Timeout";
}
Thread.Sleep(1000); // gimme a chance to see the new text
this.Refresh();
}
If I didn't set a timout on the WaitOne() the app would deadlock on the Invoke() call.
As to why I'd want to do this, I've been tasked with moving one subsystem of an app to do work in a background thread, but still have it block user's workflow (the main thread) only sometimes and for certain types of work related to that subsystem only.
You want to use the "BackgroundWorker" class, which will take most of this pain out of this for you.. but as mentioned before, you'll also want to structure it so that the main thread is updating the UI and the worker is doing the heavy lifting.
It is easyer then you might think.
Suggestion: when you need a thread to perform some occasional work, get it from the threadpool, so you will not need strange/error prone recycling code.
When you want something on another thread to update your UI, you just need a reference to the form and to call Form.Invoke passing the UI code you want the main thread to execute; it's a best pactice, in an event, to release the UI thread as soon as possible.
Ie:
private void button1_Click(object sender, EventArgs e)
{
// this is the UI thread
ThreadPool.QueueUserWorkItem(delegate(object state)
{
// this is the background thread
// get the job done
Thread.Sleep(5000);
int result = 2 + 2;
// next call is to the Invoke method of the form
this.Invoke(new Action<int>(delegate(int res)
{
// this is the UI thread
// update it!
label1.Text = res.ToString();
}), result);
});
}
Hope this helps you:)
EDIT: I am sorry, I didn't read the "blocking user workflow" part.
WindowsForms is not designed to do that, blocking the main thread is BAD (it handles the messages from the OS).
You don't have to block the user workflow via freezing a form (which would then be considered "Not Responding" by windows), the way to block user workflow is by disabling any control you want (with the Invoke method above if from another thread), even the entire form!!
Common activities which 'block' the main thread are things like opening messages boxes or modal dialog. The main code appears to block at the MessageBox or ShowDialog call.
The way those items work (and MessageBox is just a specialized modal dialog) is that they contain their own message pump while they're blocking.
Although it's a nasty hack, you can do something like this in your app by looping calling Application.DoEvents() to keep the user messages pumping while you're waiting for your other task to complete. You need to be careful because all sorts of nasty things might lead from pumping messages like this - for example someone close the form or reenter your current message handler - the modal dialogs avoid this by effectively disabling input from the form which launches them.
I did mean to say that BackgroundWorker is a better solution, if you can make it fit. I sometimes combine it with a modal 'progress dialog' to give me the background thread / message pumping and the blocking of the UI thread.
Edit - to expand on the last bit:
One approach I've used is to have a 'progress form' class, which takes a BackgroundWorker object as a constructor parameter, and contains handlers for the progress and completion events of the background worker which gets passed to it.
The form which wants the work done creates the background worker and hooks up the 'work' event (can't remember what it's called right now), and then creates a progress dialog to which it passes the background worker. It then modally shows the progress dialog, which means it will wait (but pumping messages) until the progress dialog closes.
The progress form is responsible for starting the BackgroundWorker from its OnLoad override, and closes itself when it sees the BackgroundWorker complete. Obviously you can add message text, progress bars, cancel buttons, whatever to the progress form.
structure your app so that the main thread only performs UI updates, and all other work is done on secondary threads via a work queue; then add a waiting-for-godot flag to your main thread and use it to guard the method that adds items to the work queue
out of curiosity: why do you want to do this?
You should probably restructure your code as others have suggested, but depending on the behavior you're looking for, you might also want to have a look at using a Thread.Join on your background worker thread. Join actually allows the calling thread to process COM and SendMessage events while it waits for the other thread to finish. This seems like it could be dangerous in come cases, but I've actually had a couple scenarios where it was the only way to wait for another thread to finish cleanly.
Thread..::.Join Method
Blocks the calling thread until a
thread terminates, while continuing to
perform standard COM and SendMessage
pumping.
(from http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx)
I agree with the others that are suggesting you use Background Worker. It does the heavy lifting and allows the UI to continue. You can use the Report Progress of Background Worker to initiate times where the Main Form can be set to be disabled while it performs the actions in the background and then re-enable once the 'certain instances' have completed processing.
Let me know if this helps!
JFV
If you could adjust your code so that you set a flag once a process has begun and then check that in the UI before you start an additional operation I think you'd have a much easier time coding this. I would create a delegate that could be called from the thread in the threadpool or user created thread to update on progress in the UI. Once the background process has been completed switch the flag and now normal UI operations can continue. The only caveat you need to be aware of is that when you update UI components you must do it on the thread they were created on, the main/UI thread. In order to accomplish this you can call the Invoke() method on any control that lives on that thread and pass it the delegate and parameters you need to call it.
Here's a link to a tutorial I wrote some time ago about how to use Control.Invoke():
http://xsdev.net/tutorials/pop3fetcher/
Just a code snippet: don't have much time sorry :)
private void StartMyDoSomethingThread() {
Thread d = new Thread(new ThreadStart(DoSomething));
d.Start();
}
private void DoSomething() {
Thread.Sleep(1000);
ReportBack("I'm still working");
Thread.Sleep(1000);
ReportBack("I'm done");
}
private void ReportBack(string p) {
if (this.InvokeRequired) {
this.Invoke(new Action<string>(ReportBack), new object[] { p });
return;
}
this.Text = p;
}
It is best to dispatch the work but if you must, maybe something like this. Just call this method to wait for the signal rather than calling the waitone.
private static TimeSpan InfiniteTimeout = TimeSpan.FromMilliseconds(-1);
private const Int32 MAX_WAIT = 100;
public static bool Wait(WaitHandle handle, TimeSpan timeout)
{
Int32 expireTicks;
bool signaled;
Int32 waitTime;
bool exitLoop;
// guard the inputs
if (handle == null) {
throw new ArgumentNullException("handle");
}
else if ((handle.SafeWaitHandle.IsClosed)) {
throw new ArgumentException("closed wait handle", "handle");
}
else if ((handle.SafeWaitHandle.IsInvalid)) {
throw new ArgumentException("invalid wait handle", "handle");
}
else if ((timeout < InfiniteTimeout)) {
throw new ArgumentException("invalid timeout <-1", "timeout");
}
// wait for the signal
expireTicks = (int)Environment.TickCount + timeout.TotalMilliseconds;
do {
if (timeout.Equals(InfiniteTimeout)) {
waitTime = MAX_WAIT;
}
else {
waitTime = (expireTicks - Environment.TickCount);
if (waitTime <= 0) {
exitLoop = true;
waitTime = 0;
}
else if (waitTime > MAX_WAIT) {
waitTime = MAX_WAIT;
}
}
if ((handle.SafeWaitHandle.IsClosed)) {
exitLoop = true;
}
else if (handle.WaitOne(waitTime, false)) {
exitLoop = true;
signaled = true;
}
else {
if (Application.MessageLoop) {
Application.DoEvents();
}
else {
Thread.Sleep(1);
}
}
}
while (!exitLoop);
return signaled;
}
I went with something I haven't seen posted yet which is to use MessageQueues.
The MainThread blocks while waiting for the next message on a queue.
The background thread posts different types of messages to the MessageQueue.
Some of the message types signal the MainThread to update UI elements.
Of course, there is a message to tell the MainThread to stop blocking and waiting for messages.
Seems over the top considering the windows message loop already exists somewhere, but it works.

Categories

Resources