Blog Archives
C# Application Not Responding Issue on Long Running Threads
Undoubtedly many of you have encountered the dreaded “Application Not Responding” message, programmers and non-programmers alike.
In general, this is caused by the OS misinterpretation of long delays in form refresh, even though these can easily be caused by a long running process, or any running process longer than a couple seconds actually.
If this is happening in your application after clicking on a button or event fires, a quick solution would be the easy one-liner below:
Application.DoEvents();
However, to really understand why this happening, remember that all processes (may) contain multiple threads.
In the case of your typical quick shot solution that you put together in VS in no-time, you’re likely only using a single thread.
This thread is used not only to run the processes in your application, but also to update the form window including drawing the fields and various controls on the form.
The best solution to this would really be to create a separate thread and pass off the work of your long running function to this thread.
When the work is finished, it will update our main thread (the form thread) that it has completed which we can intercept with a delegate, and notify the user of success or failure.
See snippet below.
private BackgroundWorker hardworker; //this guys works hard! private System.Timers.Timer lazyworker; //notice how this could also be achieved with thread/timer protected void btnDoAlotOfWork_Click() { //lets see who accomplishes more! ClockInLazyWorker(); ClockInHardWorker(); } private void ClockInLazyWorker() { lazyworker = new System.Timers.Timer(); //not to be confused with forms timer lazyworker.Interval = 1000; //time in milliseconds. 10 seconds is lazy for a computer! lazyworker.Elapsed += new System.Timers.ElapsedEventHandler(LetsGetAMoveOnIt()); } private void ClockInHardWorker() { hardworker= new BackgroundWorker(); mCopier.DoWork += DoWork; //all the heavy lifting is done here mCopier.RunWorkerCompleted += WorkCompleted(); mCopier.WorkerSupportsCancellation = true; OnError += ProblemWithWork(); } //motivational function name made especially for our lazy worker private void LetsGetAMoveOnIt() { //do something that takes a long time //if the data you operate on is the same as used by another thread or the form thread, make sure you wrap this block in a synclock or use a bool to track when work is in process } //created separate function for the background worker, and also to avoid synclock issues since there are two new active threads private void DoWork() { //if the data you operate on is the same as used by another thread or the form thread, make sure you wrap this block in a synclock or use a bool to track when work is in process. same goes for timer. } private void WorkCompleted() { //all finished } private void ProblemWithWork() { //hopefully not an injury on the job! that's workmans comp! }
Alot more code than simply “Application.DoEvents”.. but do not underestimate the power of multiple threads!
AppActivate In C#
AppActivate, which many of you may recognize from VB activates a window for an application which is already running, bringing the window of that app to the foreground.
In C#, there is no exact equivalent to this function, which leaves two alternatives (see link at the bottom for code examples):
Option 1 (recommended):
Use SetForeGroundWindow, described in my similar post (scroll down a bit for the code examples).
Option 2:
Add a reference to Microsoft.VisualBasic and call Interactive.AppActivate.
Although Option 2 is a little simpler/faster if you are not familiar with or ready yet to delve into Win32 API, it is not a recommended solution as there can be potential side effects of this approach.
For code examples of both options, see my similarly titled post below and scroll through for code references.
References
Start a Process in the Foreground in C# .Net Without AppActivate https://ronniediaz.com/2011/05/03/start-a-process-in-the-foreground-in-c-net-without-appactivate/
Bind Control to an Object in Windows Forms
Simple solution for basic binding in Windows Forms app. This would NOT be recommended if you are using ASP .Net, Silverlight, WCF, RIA or any other services to retrieve the data as these project types have much better support for binding to controls.
C#:
static class dataaccess { static mytype object; } //on app load object = new mytype(); //on form load tbField1.DataBindings.Add("Text", dataaccess.object.property, "Field1")