Application UI hangs on long running operation in C# WindowsForm and WPF (BackgroundWorker in C#)
Once i came across a scenario in a Windows Presentation Foundation where on click of a button i needed to call a Restful Service which returns JSON and then i needed to deserialize the JSON and do soemthing with that, but when i wrote the code in the button event, it worked successfully but one thing that i noted that unitl the all operation completes my button remains pressed and UI also not responsive , so after researching a little i came to know this:
When we have some long running code that can take much time than normal time we should execute in a background thread not on UI thread, becasue executing it in UI thread will make our application un responsive and user will get irritated, here is my code which was executing directly on UI thread in button event:
This worked fine but as it is executing all the code on UI thread the application becomes unresponsive and user has to wait for the process to complete which is not a good user experience in any software or web application, after a little reasearch i came to know about BackgroundWorker class which executes the code in separate thread not in UI thread.
This is the first version in which it was all happening on the UI thread all was fine but my button state was in pressed state and UI blocked until the service call completed and GridView populated.
Now i am showing the version in which i used BackgroundWorker class, First of all create BackgroudWorker instance assign its events:
Now write the expensive operation code in workertranaction_DoWork method:
and in workertranaction_RunWorkerCompleted bind List of Patients with Grid, as Do_Work does not executes in UI thread so we cannot access them in this method:
Now on button click we need to just call MyMethodToCallExpansiveOperation method:
When we have some long running code that can take much time than normal time we should execute in a background thread not on UI thread, becasue executing it in UI thread will make our application un responsive and user will get irritated, here is my code which was executing directly on UI thread in button event:
This worked fine but as it is executing all the code on UI thread the application becomes unresponsive and user has to wait for the process to complete which is not a good user experience in any software or web application, after a little reasearch i came to know about BackgroundWorker class which executes the code in separate thread not in UI thread.
This is the first version in which it was all happening on the UI thread all was fine but my button state was in pressed state and UI blocked until the service call completed and GridView populated.
private void btnLookup_Clicked(object sender, RoutedEventArgs e) { string url = "http://www.lyfechannel.com/channels/allscripts/allscripts_institutions.php?allscripts=XXXX&user=YYYY&password=ZZZZ"; WebRequest request = WebRequest.Create(url); request.Timeout = 500000; WebResponse response = request.GetResponse(); var reader = new StreamReader(response.GetResponseStream()); string json = reader.ReadToEnd(); var jsonAsCSharp = JsonConvert.DeserializeObject<JSONWrapper>(json); PatientGrid.DataSource = jsonAsCSharp.Patients; }
Now i am showing the version in which i used BackgroundWorker class, First of all create BackgroudWorker instance assign its events:
private void MyMethodToCallExpansiveOperation() { //Call method to show wait screen BackgroundWorker workertranaction = new BackgroundWorker(); workertranaction.DoWork += new DoWorkEventHandler(workertranaction_DoWork); workertranaction.RunWorkerCompleted += new RunWorkerCompletedEventHandler( workertranaction_RunWorkerCompleted); workertranaction.RunWorkerAsync(); }
Now write the expensive operation code in workertranaction_DoWork method:
private void workertranaction_DoWork(object sender, DoWorkEventArgs e) { string url ="http://www.lyfechannel.com/channels/allscripts/allscripts_institutions.php?allscripts=XXXX&user=YYYY&password=ZZZZ"; WebRequest request = WebRequest.Create(url); request.Timeout = 500000; WebResponse response = request.GetResponse(); var reader = new StreamReader(response.GetResponseStream()); string json = reader.ReadToEnd(); var jsonAsCSharp = JsonConvert.DeserializeObject<JSONWrapper>(json); patients = jsonAsCSharp.Patients; }
and in workertranaction_RunWorkerCompleted bind List of Patients with Grid, as Do_Work does not executes in UI thread so we cannot access them in this method:
private void workertranaction_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { PatientGrid.DataSource = patients; }
Now on button click we need to just call MyMethodToCallExpansiveOperation method:
private void btnLookup_Clicked(object sender, RoutedEventArgs e) { MyMethodToCallExpansiveOperation(); }