2012-03-26 6 views
0

私は自分のスレッドを実行しているオブジェクトを持っており、ウェブカメラからの入力を処理し、ウィンドウコントロールを更新しています。操作中、ユーザーは、現在のスレッドのサスペンド、独自のスレッドでの新しいフォームのオープン、ユーザーにinutの実行を依頼してOKをクリックするようにアプリケーションを調整したいと指示することがあります。元の履歴書。私のキャリブレーションフォームは、元のオブジェクトで別のスレッドで新しいフォームダイアログを開きます。

//Constructor() {} 

    public void StartCalibration() { 
     Debug.WriteLine("StartCalibration CALLED!"); 
     var thread = new Thread(Run); 
     thread.Start(); 
    } 


    private void Run() { 
     while (!finished) { 
      //process user input 
      this.Invalidate(); 
     } 
    } 

    protected override void OnPaint(PaintEventArgs e) { 
     base.OnPaint(e); 
     Graphics g = e.Graphics; 
     if (image != null) 
      g.DrawImage(image, new Point(15, 15)); 
    } 

が、私は

public void Run() { 
     if (calibrate == true) { 
      CalibrationForm calibrationForm = new CalibrationForm(source); 
      if (calibrationForm.InvokeRequired) 
       calibrationForm.Invoke(new MethodInvoker(calibrationForm.StartCalibration)); 
      else 
       calibrationForm.StartCalibration(); 
      if (calibrationForm.ShowDialog() == DialogResult.OK) 
       //get data from calibrationForm 
      calibrationForm.Dispose(); 
     } 
     //continue with this threads operation 

それはShowDialogの(への呼び出しのように見えますが)しかし、まだ例外をスローして、以下の持っているスレッドのように見えます

クロススレッド操作が有効でない:コントロール 'CalibrationForm'が、作成されたスレッド以外のスレッドから にアクセスしました

私は現在、自分の現在のスレッドを一時停止して、キャリブレーションフォームが完了するまで待つか、自分の目標を達成するためのより良い方法があるかどうかを知りたいのですか?

+0

ああ、答えのための喝采。私はそれが自分のスレッドでフォームをsublcassingのアイデアを放棄する必要があると推測しています... – hspim

+0

これはいくつかの詳細を見て、これは実際に致命的な終わりかどうかを確認してください?私はそれ自身のスレッドで作成している新しいフォームは、プライマリUIとのやりとり(または、とにかく必要)はありません。単一のローカライズされたタスクを実行し、結果を最初のスレッドに返すことだけが存在します.... – hspim

+0

メインスレッドですべてのUIを実行する必要があります。それらはゲームのルールです。 –

答えて

2

WinFormsでは、すべてのUI要素にメインスレッドからアクセスする必要があります。

他のスレッドでバックグラウンド処理(リモートソースからのデータの取得やログ記録など)を実行できますが、UI要素の作成や変更はできません。

0

すべてのコードをUIスレッドでUIとやりとりする必要があります。これはWinFormsの厳しいルールです。

UIを表示したり、既存のUIと対話する必要がある場合は、スレッドから同期または非同期操作を行うかどうかによって、InvokeまたはBeginInvokeを呼び出します。これらのメソッドは、UIスレッドでUIコードを実行します。

1

他の人は言っているように、メインのUIスレッドだけがUIコンポーネントとやり取りできます。

他のスレッドからUIと対話するには、2つのオプションがあります。フォームまたはコントロールでControl.InvokeまたはControl.BeginInvokeを呼び出すか、WindowsFormsSynchronizationContextを使用できます。 Example of WindowsFormsSynchronizationContext

0

だから私は私の主な問題は、主に、それは標準のダイアログウィンドウのような自タスク振る舞いだ実行するために、私の第二の形式を取得され、最終的に動作するようにこれを得ました。呼び出し側のスレッドで

public partial class CalibrationForm : Form { 

    public CalibrationForm(ISource source) { 
     InitializeComponent(); 
     this.source = source; 
     //other setup 
    } 

    private void Run() { 
     while (!finished) { 
      //process user input 
      this.Invalidate(); 
      if (this.InvokeRequired) 
       this.BeginInvoke(new MethodInvoker(Update)); 
      else 
       Update(); 
     } 
    } 

    private void OKButton_Click(object sender, EventArgs e) { 
     finished = true; 
    } 

そして...

CalibrationForm calibrationForm = new CalibrationForm(camera); 
new Thread(calibrationForm.Run).Start(); 
if (calibrationForm.ShowDialog(this) == DialogResult.OK) 
    //get data from calibrationForm 

最後のことは、彼らがShowDialog()に適切な値を返しますので、フォーム上のボタンのDialogResultプロパティを設定することを確認しましたコール。

+0

'CalibrationForm'(バックグラウンドスレッドを' OnLoad'の中など)に作成してみませんか?このようにIMOを行うことはむしろ珍しいことです。 – Groo

関連する問題