Reputation: 277
I have created a small C# application to read some data from an event log and then display some results.
The program does a basic SQL query to get its initial data(this can take some time if querying several days worth of data), then it does some processing before it displays the results.
What I am trying to do is when the Submit button is pressed a message appears stating that it will take a few moments to retrieve and process the data. So, when the submit button is pressed I create a form with a message on it and display it.
This is code from the submit button and the associated methods:
private void btnSubmit_Click(object sender, EventArgs e)
{
DisplayCustomMessageBox("Please Wait");
ProcessRequest();
HideCustomMessageBox();
}
private void DisplayCustomMessageBox(string title)
{
CustomMessageBox = new frm_Message { Text = title };
CustomMessageBox.SetText("Please wait ");
CustomMessageBox.Show();
this.Enabled = false;
}
private void HideCustomMessageBox()
{
this.Enabled = true;
CustomMessageBox.Close();
}
Whats happening is that I have the form showing BUT the text in the form never displays. If I comment out the HideCustomMessageBox method the form displays without the text until the ProcessRequest method finishes. Then the form will finally display the text.
I assume its some sort of timing issue but I am not sure about how to fix it.
Thanks in advance.
Upvotes: 1
Views: 158
Reputation: 61666
I'd do this using a modal dialog (Form.ShowDialog
) and Task.Run
to run ProcessRequest
on a background thread. Async/await
is very handy while implementing this.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsForms_21739538
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// test the btnSubmit_Click
this.Load += async (s, e) =>
{
await Task.Delay(2000);
btnSubmit_Click(this, EventArgs.Empty);
};
}
private async void btnSubmit_Click(object sender, EventArgs e)
{
try
{
// show the "wait" dialog asynchronously
var dialog = await DisplayCustomMessageBox("Please Wait");
// do the work on a pool thread
await Task.Run(() =>
ProcessRequest());
// close the dialog
dialog.Item1.Close();
// make sure the dialog has shut down
await dialog.Item2;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
// show a modal dialog asynchrnously
private async Task<Tuple<Form, Task<DialogResult>>> DisplayCustomMessageBox(string title)
{
//CustomMessageBox = new frm_Message { Text = title };
var CustomMessageBox = new Form();
CustomMessageBox.Text = "Please wait ";
var tcs = new TaskCompletionSource<bool>();
CustomMessageBox.Load += (s, e) =>
tcs.TrySetResult(true);
var dialogTask = Task.Factory.StartNew(
()=> CustomMessageBox.ShowDialog(),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
// await the dialog initialization
await tcs.Task;
return Tuple.Create(CustomMessageBox, dialogTask);
}
void ProcessRequest()
{
// simulate some work
Thread.Sleep(2000);
}
}
}
Upvotes: 0
Reputation: 3680
Here is some threaded code to get you started.
private void btnSubmit_Click(object sender, EventArgs e)
{
DisplayCustomMessageBox("Please Wait");
Thread t = new Thread(()=>
{
ProcessRequest();
this.BeginInvoke(new Eventhandler((s,ee)=>{
HideCustomMessageBox();
}));
});
t.Start();
}
Upvotes: 1