2017-10-08 11 views
2

私は、10^20より小さい数値の素因数分解を計算するWindowsフォームアプリケーションを作成しようとしています。しかし、10^12より大きい数字の場合、アプリは結果を出す前に数秒間フリーズし始めます。だから私は別々に答えを計算するスレッドを作成しようとしました。コードは次のとおりです。入力を読み取っている間に計算するウィンドウフォームアプリケーション

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; 
     } 
    }    

新しいスレッドを作成しないと、アプリケーションは動作しますが、出力は常に空になります。誰かがどのようにこのスレッドを実行し、それを修正する方法を説明することができますか?

+2

'BackgroundWorker'、特に' RunWorkerCompleted'を読んでください。 – mjwills

+0

数字が大きすぎるとバックグラウンド計算が実用的にならないという事実に対処しなければなりません。スレッドを停止して再起動しようとすると、競合状態に苦しんでいる多くの問題が発生します。単純なままで、値が十分に小さいときはすぐに結果を計算し、そうでないときは「計算」ボタンを表示させます。 –

答えて

2

スレッドを開始しているときと、結果を表示しようとした直後のためです。あなたはスレッドが終了するのを待つ必要があり、それを行うには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

あなたは、バックグラウンドワーカーを宣言するときbackgroundWorker.WorkerSupportsCancellation = true;を使用する必要が取り消しを有効にするには。これを考慮に入れてコードサンプルを更新しました。

+0

ユーザーはどのように操作をキャンセルできますか? –

関連する問題