Use Threads to Keep UI Responsive and Events to Show Status | | Use Threads to Keep UI Responsive and Events to Show Status to keep the user informed of progress. This will help to keep users from "clicking around" if they know what is happening.
The last thing you want in a Windows application is a user who thinks nothing is happening and they start to "click around." The best way to prevent this is by keeping the UI responsive and to display status and progress. This is especially needed if you are doing .NET Remoting over the Internet and you cannot guarantee instant respone to every request by the user.
The example that I will use is for a text editor that I am writing for a .NET Remoting project. In this example, instead of saving the contents of the Editor to a file on the user's hard drive, I send the contents of the Editor (not the complete text, rather the independent documents that are concatenated into one document in the Editor) to the server. The user is working remotely and we do not want them to save files on their hard drive. Everything is saved on the remote server. Regardless, when the user clicks the File Save Menu, the Click Event that is fired is shown below. Notice that I do not save the file if the Editor's Dirty Property is not set to true. However, if the Dirty Property is true, I call the SaveDoc method on an asynchronous thread. Saving the document can take a while, depending on the status of the server and the Internet. Before starting the new Thread, I set the status panel to tell the user that the file is being saved.
private void mnuFileSave_Click(object sender, System.EventArgs e)
{
// dont send the data back to the server if no changes made
if (!Dirty)
return;
this.pnlStatus.Text="Saving Merged Doc to Server...";
Thread t = new Thread(new ThreadStart(SaveDoc));
t.Start();
}
|
The SaveDoc method is shown next. I do not show the code required to send the document components to the server since that is not germaine to this article and is a rather involved process. What I want to illustrate is the sending of status back the Editor main thread when the process is complete. That is done with the SendStatus("Done") statement. The reason that I cannot set the status panel from the thread is that you cannot reference a Windows Form Control from an asychronous thread. You will get the error "Controls created on one thread cannot be parented to a control on a different thread." See my article on this subject.
/// <summary>
/// This method runs on a thread to keep the ui responsive
///
private void SaveDoc()
{
// save the components of the document to the server
//....
this.SendStatus("Done");
this.Dirty=false;
} // method: SaveDoc
|
In order to create the event I use the following two statements in the declaration section of the form.
public delegate void DelegateSendStatus(string status);
public event DelegateSendStatus SendStatus;
|
In the Form_Load Event of the form I sink the event to handle the SendStatus event with the following line of code.
this.SendStatus+=new DelegateSendStatus(EditorForm_SendStatus);
|
Finally, the handler for the event is shown below. This event will fire when the SaveDoc method raises the SendStatus event. Obviously all of this code is in the same form, the EditroForm, but the event and the handling of the event can be in different Classes, files, whatever.
private void EditorForm_SendStatus(string status)
{
this.pnlStatus.Text=status;
}
|
Using this strategy will keep your users informed, which makes them feel secure when response is not instantaneous. This will hopefully keep them from clicking around and that will make you feel more secure, if you know what I mean... |