2009-06-11 15 views
4

私は別のスレッドで長時間実行されるメソッドを開始するメインGUIを使用しています。 この別のスレッドの中から、新しいフォームを作成して表示する必要があります。 しかし、私がこの新しいフォームを表示すると、すべてのコントロールが止まって、ウィンドウに「応答していません」と表示されます。非GUIスレッド内からフォームを作成する方法C#

これを解決する最良の方法はどれですか?

よろしく

トーマス

答えて

4

メインGUIクラスに新しいGUIを作成するコードを入れて、その後、メインGUIのInvokeメソッドを呼び出し、またはメインGUIの時に知っておくために購読することができイベントを発生させます新しいGUIを起動します。後者を選択する場合は、InvokeRequiredを使用して、新しいGUIを直接作成するメソッドを呼び出すことができるかどうか、またはInvokeを使用してGUIスレッドに戻って新しいGUIを作成する必要があるかどうかを確認してください。

0

Form.ShowDialogの代わりにForm.Showを使用してください。 BackgroundWorkerを使用して並行タスクを実行することもできます。

2

Control.BeginInvoke/Invokeとそのすべてを知る必要があります。すべてのUI操作はメインスレッド(UIスレッド)で実行する必要があることを覚えておいてください。これは、メッセージポンプを所有するスレッドであるためです。 UIアクションが発生するには、そのスレッドにコールバックする必要があります。ここでさらに支援するためにhttp://weblogs.asp.net/justin_rogers/pages/126345.aspx

基本を強調表示する必要があり、完全な作業コードの例です:

はここでBeginInvokeを/起動のものにイントロです。

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     var worker = new Worker(this); 
     worker.Start(); 
    } 

    public void updateLabel(int value) 
    { 
     if(label1.InvokeRequired) { // check if on UI thread 
      //If true use begin invoke to call update on UI thread 
      //this calls the anonymous delegate in the UI thread 
      //that then calls the updateLabel function again to set the label's text 
      label1.BeginInvoke(new MethodInvoker(() => this.updateLabel(value))); 
      return; 
     } 

     label1.Text = value.ToString(); 
    } 

    public void showNewForm() 
    { 
     if(this.InvokeRequired) { // check if on UI thread 
      this.BeginInvoke(new MethodInvoker(this.showNewForm)); // we need to create the new form on the UI thread 
      return; 
     } 

     var anotherForm = new Form1(); 
     anotherForm.Show(); 
    } 
} 

class Worker 
{ 
    private volatile bool stop = false; 
    private Form1 form; 

    public Worker(Form1 form) 
    { 
     this.form = form; 
    } 

    public bool Stop 
    { 
     get 
     { 
      return stop; 
     } 
     set 
     { 
      stop = value; 
     } 
    } 

    public void Start() 
    { 
     var thread = new Thread(this.work); 
     thread.IsBackground = true; 
     thread.Start(); 
    } 

    private void work() 
    { 
     int i = 0; 
     while(!stop) { 
      i++; 
      Thread.Sleep(100); 

      form.updateLabel(i); 
      if(i == 50) { 
       form.showNewForm(); // call into form 
       // can also do the invokerequired check here and create new form w/ anonymous functions 
       // however, I'd recommend keeping all the UI code in the same place. 
      } 
     } 
    } 
} 
関連する問題