I've got an application written in C# 2.0, and am trying to speed up my reporting a bit. On the main form, I have a button that will create a report that can take quite some time. While this report is being created, my main form goes unresponsive. The button doesn't even pop back up while I'm waiting on it. I figured I'd spin off a thread and have it create the report. It worked, but the second the form is loaded, it goes away. How can I get this form to load separate from my main thread, and then somehow come back so it doesn't go away

Trouble understanding threading
scott00
event EventHandler ReportCreated;
public ReportCreator(PhonePageParameters phonePageParameters)
{
InitializeComponent();
Text = Application.ProductName;
ThreadStart threadStart = delegate
{
List<PhonePage> phonePageList = PhonePageManager.Read(phonePageParameters.sxs, phonePageParameters.reportType);
PhonePageXtraReport xtra = new PhonePageXtraReport(phonePageList);
Thread.Sleep(0);
xtra.CreateDocument();
Thread.Sleep(0);
report = xtra;
if (ReportCreated != null)
{ ReportCreated.Invoke(this, EventArgs.Empty); }
};
thread = new Thread(threadStart);
ReportCreated += new EventHandler(ReportCreator_ReportCreated);
}
private void ReportCreatorForm_Load(object sender, System.EventArgs e)
{
if (thread != null)
{
thread.Start();
}
}
void ReportCreator_ReportCreated(object sender, EventArgs e)
{
Close();
if (Report != null)
Report.ShowPreview();
}
helpPlease176795
First I would like to point out that you probably should use the BackgroundWorker if you're doing C# 2.0. But if you insist on using the code you provided I think it would be better if you removed the "Close();" in the eventhandler as the form you're closing is holding the reference to the Report (I guess).
raceirolg
Then do your work in the RunWorkerAsync() method.
See here for details: http://msdn2.microsoft.com/en-US/library/4852et58.aspx
The key thing is you do the work in a different thread from the user interface thread. The user interface thread just sits around waiting for the BackgroundWorker's "RunWorkerCompleted" event to fire.
I commonly have a boolean variable in the form that I set to true in response to the RunWorkerCompleted event. I inspect that variable to prevent the user from doing anything they shouldn't until the work is done (e.g. when handing FormClosing, I can prevent the form from closing).
Bonnie Colleen
MrMoke
I guess that you should create a class, that has a run method, and when this run method is called, your 'task' (creating the report) should be done on a separate thread. Then, when this is finished, your class should raise an event, and you can open the 2nd form from this event-handler.
For instance:
public class CreateReportTask
{
public event EventHandler ReportCreated;
public void Run()
{
Thread t = new Thread (new ThreadStart(DoWork));
t.Start();
}
private void DoWork()
{
// Create the report
// When finished, raise the event.
}
private void OnTaskFinished()
{
if( ReportCreated != null )
{
ISynchronizeInvoke s = ReportCreated.Target as ISynchronizeInvoke;
if( s != null && s.InvokeRequierd )
{
s.Invoke (ReportCreated, new object[] {this, EventArgs.Empty});
}
else
{
ReportCreated (this, EventArgs.Empty);
}
}
}
}
Before you launch the task, you can assigne an eventhandler to the event, and this event-handler can show your 2nd form.
(You can offcourse use a custom delegate instead of EventHandler, so that you can create and pass your own event-arguments).
You might also have a look at the BackgroundWorker object in .NET 2.0, since this has almost the same behaviour as my example. But, since I'm still mainly using .NET 1.1, I always create my own Task pattern.