1

I'm trying to run a function after a thread has completed running. My thread starts when an UI button is pressed and the thread takes a while to complete.
Once it's done running I want to call a function. Here is the code I tried so far. When I try to run my code the thread never executes and the application freezes. Any suggestion on how to fix this would be helpful.

public bool StartProbe()
{
    if (File.Exists(Path.Combine(ObsProbeFolder, "probePJM.exe")))
    {
        ThreadStart ProbeThreadStart = new ThreadStart(() =>
        // right side of lambda    
            {
               // does stuff
            });

            ProbeThread = new Thread(ProbeThreadStart);
            ProbeThread.Priority = ThreadPriority.BelowNormal;
            ProbeThread.SetApartmentState(ApartmentState.STA);
            ProbeThread.Start();

    }
    else
    {                      
        return false;
    }

    // waiting for thread to finish 
    ProbeThread.Join();
    // run a function
    loadData();

    return true;
} 
VMAtm
  • 27,342
  • 17
  • 79
  • 118
Satish
  • 195
  • 1
  • 2
  • 12

2 Answers2

0

I would use a BackgroundWorker:

Worker = new BackgroundWorker();
            Worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
            Worker.DoWork += Worker_DoWork;

            Worker.RunWorkerAsync(new BackgroundArguments()
            {
                // arguments
            });

Work on alternate thread:

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{       
    // do stuff
}

Return to UI thread:

private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       // load data or whatever on UI thread
    }
mjhouseman
  • 154
  • 2
  • 18
  • Why use such an old structure as BackgroundWorker, if you can use TPL and/or await? – VMAtm Feb 10 '17 at 19:17
  • There is nothing wrong with using BackgroundWorker, especially for a single process such as the user described. I agree that TPL is better for running multiple processes, but for a single process they are virtually interchangeable. – mjhouseman Feb 13 '17 at 20:30
0

Do not use the BackgroundWorker - it's quite an old class, which, I hope, will be called obsolete someday by MS.

As you say, that you have a button, create an async void event handler for fire-and-forget scenario. As you do check some exe file, I assume that you're running some Process in background. Also, you do not need a thread to run your process - you're joining it and that's why the UI is hanging.

private async void button_Click(object sender, EventArgs e)
{
    // wait for a result from outer process
    var result = await RunProcessInBackGround();
    //do whatever you need in the UI-context
    loadData(result);
}

// T is a type of the result, should be changed
private async Task<T> RunProcessInBackGround()
{
    var tcs = new TaskCompletionSource<T>();
    // run your process
    var process  new Process {/* your params here */};
    process.Exited += (sender, args) =>
        {
            // here your process has already done his job
            tcs.SetResult(result);
            process.Dispose();
        };
    // process will start as a separate process, no need to create a thread to wait for it
    process.Start();
    // return the task which will be awaited for
    return tcs.Task;
}
Community
  • 1
  • 1
VMAtm
  • 27,342
  • 17
  • 79
  • 118