-2

Possible Duplicate:
Timing issue - DGV refreshes before process amends the data

I've got the following code

private void btRunReport_Click(object sender, EventArgs e){ 

    Process p = new Process(); 
    p.StartInfo.FileName = @"\\fileserve\department$\ReportScheduler_v3.exe"; 
    p.StartInfo.Arguments = "12"; 
    p.Start(); 
    p.WaitForExit(); 
    InitializeGridView(); 
} 

p will update a database table X. InitializeGridView updates a DGV which reflects table X.

Problem is that if p takes 10minutes to run then the winForm is frozen witing before it hits InitializeGridView(). What I need help with is how do i make the form start the process in a seperate thread that works behind the scenes and runs InitializeGridView() ?

Community
  • 1
  • 1
whytheq
  • 34,466
  • 65
  • 172
  • 267
  • You can't start a process in a thread as such, that is back to front, and firing off a thread to start the process would be pointless. if you didn't have p.WairForExit your code would continue on to InitializeGridView(); straight away. – Ben Robinson Mar 15 '12 at 09:59
  • Have a read of [Threading in C#](http://www.albahari.com/threading/) from C# 4.0 in a Nutshell - what you're trying to do is reasonable easy mostly. **edit**: missed the fact you were trying to run an exe, either way it's a good article – akiller Mar 15 '12 at 10:02
  • I think the only way to do this and facilitate safe cancellation is to use a seperate AppDomain... – MoonKnight Mar 15 '12 at 10:05
  • Not a duplicate but a follow up question IMHO. – Till Mar 15 '12 at 11:12
  • @till - agreed - the prvious thread cam to an end and this question deserves seperate thread. although think I might have asked this question in the comments of the prev post (I'll delete that) – whytheq Mar 15 '12 at 13:01

1 Answers1

1

If you need your InitialilzeGridView() Method to run after the process has finished:

  1. Make available Dispatcher.CurrentDispatcher as _currentDispatcher.
  2. Start the Process in a seperate Thread and have it WaitForExit() there.
  3. Have the Thread call your InitializeGridview() Method via _currentDispatcher.BeginInvoke.

Here's some code to get you going:

Note: You will need to add a Reference to WindowsBase via the Add Reference dialog of your project.

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Threading;

private readonly Dispatcher _currentDispatcher = Dispatcher.CurrentDispatcher;
private delegate void ReportingSchedulerFinishedDelegate();

private void btRunReport_Click(object sender, EventArgs e)
{
    btRunReport.Enabled = false;
    btRunReport.Text = "Processing..";
    var thread = new Thread(RunReportScheduler);
    thread.Start();
}

private void InitializeGridView()
{
    // Whatever you need to do here
}

private void RunReportScheduler()
{
    Process p = new Process();
    p.StartInfo.FileName = @"\\fileserve\department$\ReportScheduler_v3.exe";
    p.StartInfo.Arguments = "12";
    p.Start();
    p.WaitForExit();
    _currentDispatcher.BeginInvoke(new ReportingSchedulerFinishedDelegate(ReportingSchedulerFinished), DispatcherPriority.Normal);
}

private void ReportingSchedulerFinished()
{
    InitializeGridView();
    btRunReport.Enabled = true;
    btRunReport.Text = "Start";
}
Till
  • 3,084
  • 17
  • 18
  • Till - your solution seems to works perfectly - I just need to research it to find out how it works now! – whytheq Mar 15 '12 at 14:03
  • It's pretty straight forward: run the long running RunReportSchedule in its own thread. Problem with a background thread is that you may not access elements handled by your main GUI thread directly. _currentDispatcher will hold a reference to the dispatcher from your GUI thread and to that you can pass the instruction to run ReportSchedulerFinished via a delegate after it has finished to prepare the data. – Till Mar 15 '12 at 14:47