A Window Form app that calculate while reading input

Viewed 48

I'm trying to write a Windows Form app that calculate the prime factorization of numbers smaller than 10^20. But with numbers bigger than 10^12, the app start to freeze a few second before giving the result. So I tried to create a thread to calculate the answer separately. Here's the code:

    class fact
    {
        static long[] res = new long[202];
        static long num;
        public static string output;

        static void calcFact(long n)
        {
            //calculate prime factorization into array res
        }    

        static void call()
        {
            calcFact(s);
        }

        public static void execute(string input)
        {
            s = long.Parse(input);
            ThreadStart childref = new ThreadStart(call);
            Thread childThread = new Thread(childref);
            childThread.Start();
            for (int i = 0; i < len; i++) output += res[i].ToString() + " ";
        }
    }

    private void InputBox_TextChanged(object sender, EventArgs e)
    {
        if (InputBox.Text != "")
        {
            fact.execute(InputBox.Text);
            output.Text = fact.output;
        }
    }            

Without creating a new thread, the app work, but now the output is always empty. Can someone explain how did this thread run and how to fix it?

1 Answers

It's because you're starting the thread and immediately after you're trying to display it's results. You have to wait for the thread to finish and to do that you can use a BackgroundWorker.

class fact {
/*...*/
static void calcFact(long n, BackgroundWorker worker)
    {
        if (worker.CancellationPending == true)
        {
            e.Cancel = true;
            break;
        } 
        //do this code in your loop to break and stop the calculation
        //calculate prime factorization into array res
    }   

var backgroundWorker = new System.ComponentModel.BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
        backgroundWorker_RunWorkerCompleted);
backgroundWorker.WorkerSupportsCancellation = true;

private void backgroundWorker_DoWork(object sender, 
        DoWorkEventArgs e)
    {   
        BackgroundWorker worker = sender as BackgroundWorker;
        // Assign the result of the computation
        // to the Result property of the DoWorkEventArgs
        // object. This is will be available to the 
        // RunWorkerCompleted eventhandler.

        var result = calcFact((long)e.Argument, worker);
        var outputBkw = string.Empty;
        for (int i = 0; i < len; i++) outputBkw += res[i].ToString() + " ";
        e.Result = outputBkw;
    }

    private void backgroundWorker_RunWorkerCompleted(
        object sender, RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown.
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            // Next, handle the case where the user canceled 
            // the operation.                
            resultLabel.Text = "Canceled"; // or any other method you are showing status...
        }
        else
        {
            // Finally, handle the case where the operation 
            // succeeded.
            resultLabel.Text = e.Result.ToString();
            //Here you can use the result with the numbers calculated.
            // At this point you can have an event in the calc class to signal that the work is finished.
        }            
    }


private void cancelAsyncButton_Click(object sender, EventArgs e)
    {
        if (backgroundWorker.WorkerSupportsCancellation == true)
        {
            // Cancel the asynchronous operation.
            backgroundWorker.CancelAsync();
        }
    }

UPDATE

To enable cancellation you have to use backgroundWorker.WorkerSupportsCancellation = true; when declaring the background worker. I've updated the code sample to take this into consideration.

Related