I have an application that I made to connect to a device using telnet, the application freeze/crash when I started it .. I have System.Threading.Thread.Sleep(3000); in couple locations of the application. I was wondering, is there a way to have the application active and buttons are useable but the some operations are only impacted by the sleep operation?
Thanks in advance.
Don't use Thread.Sleep, especially on the UI thread. This will cause a hang - by design.
Since you're using .NET 4.5, you can use await Task.Delay(3000); to asynchronously "sleep", which won't block the UI. However, this is typically a sign of a poor design - "waiting" is something that really shouldn't need to happen in a UI application in general. There are typically better approaches, such as using await on the asynchronous operation for which you're waiting, etc.
This requires a bit of an explanation. There are some threads that are special in this case the ui thread where the rendering of your Ui happens and the events from the input devices are handled. If this thread spends time doing any calculations windows will state that your application has frozen. Since you are using Thread.Sleep on it you get this result.
Articles to understand the problem
http://msdn.microsoft.com/en-us/library/ms741870(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd744765(v=vs.85).aspx
Recommended Solutions
On the Button press dispatch a thread that goes and does the work that you need to happen. On the meantime change the cursor for the mouse to indicate that work is happening or show a progress bar. Once it finishes you can fire(dispatchet) an event that changes the ui.
I would do something similar to:
// The Work to perform on another thread
ThreadStart start = delegate() { // ... // This will work as its using the dispatcher
DispatcherOperation op = Dispatcher.BeginInvoke( DispatcherPriority.Normal, new Action<string>(SetStatus),
"From Other Thread (Async)");
DispatcherOperationStatus status = op.Status; while (status != DispatcherOperationStatus.Completed) { status = op.Wait(TimeSpan.FromMilliseconds(1000));
if (status == DispatcherOperationStatus.Aborted)
{ // Alert Someone } } }; // Create the thread and kick it started! new
Thread(start).Start();
More Examples at:
http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
If you are calling sleep within your application it will do just that. If you do not want your application to hang, you will need to create a new thread that does whatever monitoring and waiting you want it to do, if a particular condition you are looking for is met, then use a callback to your parent thread to perform whatever task you want to do.
Related
I made a short program which has just a button. When the button is pressed, functionA is executed, which also uses functionB and functionC. Inside functionA is a loop which executes functionB and functionC X amount of times. At the end of each loop, the progressbar gets incremented by 1. At the beginning of functionA, before the loop, there's a webservice which pulls data from a website, and passes that onto B and C for processing (data file manipulation and saving to disk).
My problem is that everything works fine, but while functionA is still running, the GUI is stuck, so I can't close/minimize/drag the window around, I have to wait until A is done. I researched and they say I should use BackgroundWorker, but as being a new programmer, I've no idea on how to use it. Can someone give me a simple way to use it?
The progressbar loads fine, but it's just that while the function is running, the whole window is frozen, and I want it so I can move the window around, etc while the program is running, instead of waiting until the function is complete.
Thank you!
Call your function asynchronously like the following and it will not freeze the UI.
private async void BeginProcessingAsync(Data d)
{
//Execute the long running task asynchronously
await Task.Run(() => functionA(d));
//Anything after the await line will be executed only after the task is finished.
anotherFunction(d); // if you have one..
}
To run your task, simply call BeginProcessingAsync(d);. Also, please note: If you're using newer versions of .NET, you might have to use await Task.Factory.StartNew(() => functionA(d)); instead of the above
Overall, you'll want to make sure your GUI doesn't get updated from another thread. Instead, the messages should go to a threadsafe location. For instance, you could have the thread building into something like a database and have the GUI using a timer to look for updated data flags.
There is a question with a lot more detail using delegates here.
Marc's answer was the simplest and best, in my opinion:
///...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 Dotnet Perls:
A Background Worker makes threads easy to implement in Windows
Forms. Intensive tasks need to be done on another thread so the UI
does not freeze. It is necessary to post messages and update the user
interface when the task is done.
Also, from MSDN, look at Task-based Asynchronous Pattern (TAP) if you're using C# 5.
The Task-based Asynchronous Pattern (TAP) is based on the
System.Threading.Tasks.Task and System.Threading.Tasks.Task
types in the System.Threading.Tasks namespace, which are used to
represent arbitrary asynchronous operations. TAP is the recommended
asynchronous design pattern for new development.
I'm need to display some form of feedback to the user, while a small process (7-10 seconds) takes place in the background.
I had no issues in the past using separate threads and BackgroundWorkers in Windows Forms, but its proving difficult in WPF.
I have read many articles, in this respect, and how I should be using dispatchers in WPF to start a new thread, etc. However, when I try to use a BackgroundWorker to display a form of waiting image feedback, it simply remains static.
I don't believe that it matters, but it uses mui from FirstFloor (https://github.com/firstfloorsoftware/mui).
I'm trying to use the built-in ProgressRing feature (which works no problems when run within the same thread and there are no other major tasks running in the background.
Adding a BackgroundWorker, brings an exception due to cross thread access of objects, even though many blogs states that BackgroundWorks in WPF are cross thread aware and safe to run.
The following is the closest code that generates what I need.
private async void MyTaskProcess()
{
await Dispatcher.BeginInvoke(DispatcherPriority.Send, new ThreadStart(() =>
{
try
{
//Update the waiting ring image
ProgressRing.IsActive = true;
}
catch
{
ProgressRing.IsActive = false;
MessageBox.Show("Exception Thrown");
}
}));
await Dispatcher.BeginInvoke(DispatcherPriority.Background, new ThreadStart(() =>
{
try
{
//Run the main MS Excel export function
Export2Excel();
ProgressRing.IsActive = false;
}
catch
{
MessageBox.Show("Exception Thrown");
}
}));
}
Any feedback is appreciated.
The way you do this in a modern WPF application is to start a new Task in which you do the work; under the covers this will perform the work on a thread pool thread:
Task.Factory.StartNew(this.DoWork)
Now in DoWorkto report progress you InvokeAsync back to the main thread whenever the porgress count changes:
void DoWork()
{
foreach(var item in this.WorkItems)
{
// Do something
// Report Progress
++progress
Application.Current.Dispatcher.InvokeAsync(() => this.Progress = progress);
}
}
Adding a BackgroundWorker, brings an exception due to cross thread access of objects, even though many blogs states that BackgroundWorks in WPF are cross thread aware and safe to run.
BackgroundWorker works fine with WPF, as long as you create and start the BGW on the UI thread. (As a side note, BGW has the same restriction on Windows Forms). As other commenters have noted, the proper way to do progress updates with BGW is using ReportProgress, not Dispatcher.
However, I'd recommend using the newer Task.Run with IProgress<T> for progress updates. I have a blog post that compares/contrasts the old BGW progress updates with the new IProgress<T>-based progress updates.
It's difficult to say what your code should look like, since the code you posted doesn't actually run anything on a background thread. In particular, if Export2Excel must be run on the UI thread, and that's all your work is doing, then there's no point in using BGW or Task.Run at all, since nothing can run on the background thread anyway.
you go, to the below link written by me and read carefully.I hope you will definetily solve your problem:
Threads in WPF
I've used Visual Studio 2013 to build a C# application with a single form, and the application has two routines that update the screen. The routines that update the screen need to run on the main thread, so my own threads (which don't interact with the screen) call the BeginInvoke method on the main form when updates are required. However, something is happening somewhere in the application with the result that the two update routines stop executing. I've put logging into the app to track the calls to BeginInvoke and the execution of the update routines, and I can see that when this problem occurs, the BeginInvoke calls are made, but then nothing. When this happens, the whole application seems to freeze. I can't think of what might be causing this. How can I debug this? Is there any way of looking at what's queued to run on the main thread? When I run in debug and break into the application, all threads look normal, and the main thread doesn't appear to be doing anything, so why isn't it processing my pending update tasks?
The Control.BeginInvoke() adds the delegate to an internal thread-safe queue. And posts a message to the UI thread to tell it to go have a look in that queue. The message loop inside Application.Run() gets that message and goes about emptying the queue again, executing the delegates.
So if you don't see this happening then the most obvious reason is that the UI thread isn't inside the Application.Run() loop. A standard mistake you could make is waiting for the thread to complete for example. Very likely to cause deadlock. Never wait, if you need to run code after the thread completes then consider BackgroundWorker's RunWorkerCompleted event or TaskScheduler.FromCurrentSynchronizationContext().
The not-so-obvious failure mode of not seeing anything happening is that you are calling BeginInvoke() far too often. If you do this more than ~1000 times per second, give or take, then you'll flood that internal queue with too many delegates. The UI thread will actually be busy emptying that queue but can never catch up, always finding yet another delegate in the queue after executing one. It goes catatonic when this happens, not taking care of its normal duties anymore. Like responding to input and painting the windows. No fix for this, other than limiting the rate at which you call BeginInvoke(). Do keep the target in mind, you only have to do it as often as the user's eyes can perceive. Updating the UI at a rate more then 25 times per second is just wasted effort.
This might be due to the two update routines attempting to update the UI at the same time. I've seen strange UI behaviour, e.g. partially updated controls, when many UI updates occur in a short space of time when triggered by multiple interleaved events. The two routines are different routines, yes?
A possible way to solve this is to use asynchronous delegate invocation on the UI thread. In the code below I've assumed that your UI is a WinForms Form, and I've named the two routines UpdateA and UpdateB.
private bool isUpdating;
public delegate void UpdateDelegate();
private void UpdateA()
{
if (isUpdating)
{
this.BeginInvoke(new UpdateDelegate(UpdateA));
}
else
{
isUpdating = true;
try
{
// ... do UI updates for A
}
finally
{
isUpdating = false;
}
}
}
private void UpdateB()
{
if (isUpdating)
{
this.BeginInvoke(new UpdateDelegate(UpdateB));
}
else
{
isUpdating = true;
try
{
// ... do UI updates for B
}
finally
{
isUpdating = false;
}
}
}
By the way, I didn't use lock above to synchronise access to flag isUpdating, on the assumption that both UpdateA and UpdateB execute on the UI thread. They are invoked asynchronously by the worker threads via BeginInvoke.
I've got a WPF application that does a lot of talking to a remote server, so to keep the UI nice and responsive I put those operations in a second thread. There are a few possible, though unlikely, instances where that thread would just hang, blocking forever. Is there a simple way for me to implement a "cancel" button that doesn't involve calling thread.Abort()? I see a lot of people advise against using that, and I don't want to leave any unreleased resources. Perhaps a way to force the thread to throw an exception?
I specify in the title that this isn't a background worker because the program doesn't use those. It's already coded up with plain old threads.
I absolutely agree with comments that you need to fix what's broken, because that's the real issue, but if you can't at the moment, and need to continue operating. If you are on .Net 4.0, use the Task library. You can create a task and pass it an action that will execute on a different thread. The key is that you can pass a cancellation token to that task.
http://msdn.microsoft.com/en-us/library/dd997396.aspx
if you fire the same action over and over, you can also check the task status and do something about that.
//this is just a sample
if (myTask != null) //meaning it's still exe'ing your action
{
if (myTask.Status == TaskStatus.Faulted) //there's some kind of a problem with exe'ing it
myTask = null; // could reset to run the action again
else
return; //let the task finish
}
myTask = Task.Factory.StartNew (() =>
{
ExecuteUMyAction ();
});
I'm showing an animation while my control is loading the data. When the thread finishes, I hide the animation and show the control. So I'm executing this code from a thread:
protected void InvokeEnableBackControl()
{
if (this.InvokeRequired)
{
this.Invoke(new OpHandler(EnableBackControl));
}
else
{
EnableBackControl();
}
}
Sometimes, when I execute this code, the main thread gets hanged in the following code:
protected virtual void EnableBackControl()
{
if (overlayAnimation.TargetControl != null)
{
overlayAnimation.TargetControl.BringToFront();
}
overlayAnimation.SendToBack();
overlayAnimation.Enabled = false;
overlayAnimation.Visible = false;
}
I'm not sure if it's hanged setting the Enable or Visible property. Do you know any circumstance that may hand the application calling these properties from a Control.Invoke?
Note that Control.Invoke is synchronous, so it will wait for EnableBackControl() to return. Consider using Control.BeginInvoke, which you can "fire and forget."
See this answer: What's the difference between Invoke() and BeginInvoke()
I've run into problems before when I'm executing .Invoke on a background thread while my main thread is still busy - this gives the impression that the app is hung, because the .Invoke just sits there, waiting for the main thread to respond that it's paying attention. Possible causes:
Your main thread is blocked waiting for something
Your main form currently had a modal dialog up, so it's not listening to new requests
Your main thread is spinning, either continually checking if something is finished or doing new work. In my case, the main thread spent the first minute spinning up background threads in a tight loop, so it wasn't listening for any .Invoke requests from background threads.
When you attach the debugger, pay special attention to what your main control MessagePump thread is doing - I suspect its lack of attention is the cause of your trouble. If you identify that it's a tight loop in your main thread that's not responding, try inserting a .DoEvents in the loop, which will pause execution and force the main thread to empty the message pump and route any outstanding requests.
Run in debug, make app hang and then pause debug in Visual Studio and inspect threads.
What I discovered is that the actual drawing/painting of controls can be quite slow, esp if you have a lot of them and/or use double buffering for smooth refresh. I was using BeginInvoke to update a listview control from data I was receiving from a socket. At times the updates were happening so fast that it was freezing the app up. I solved this by writing everything I received in the sockets async receive to a queue, and then in a seperate thread dequeuing the data and using BeginUpdate and EndUpdate on the listview and doing all the outstanding updates in between. This cut out a ton of the extra redrawing and made the app a lot more responsive.
You have to use BeginInvoke inested Invoke see this Link