2016-07-13 7 views
0

私はそれにいくつかのボタンがあるメインフォームでこのアプリを持っている。ボタンはMainForm UIでの作業を含む時間のかかる作業を行います。このアプリケーションの複数のインスタンスを同時に実行する必要があるので、私はMainFormHostを作成することにしました。各タブの下にあるMainFormのインスタンスを作成してそこにホストするタブコントロールを持つフォームです。そして、これまでのところすべてが大丈夫でした。問題はMAinForm1上のボタンをクリックするとうまく始まりますが、MainForm2のボタンをクリックすると、MainForm1ボタンのプロセスがMainForm2プロセスの後ろにキューイングされます。その後、タブコントロール/キューイングのアプリケーションの複数のインスタンスをホスト

MainForm GetMainFrom(TabPage tabPage) 
{ 
tabPage.Invoke(new Action(() => 
{ 
    mainForm = new MainForm(); 
    mainForm.TopLevel = false; 
    mainForm.FormBorderStyle = FormBorderStyle.None; 
    mainForm.Dock = DockStyle.Fill; 

    _mainForms.Add(mainForm); 
    tabPage.Controls.Add(mainForm); 
    mainForm.Show(); 

})); 
} 

そしてメソッドを呼び出す:

var mainFormThread = new Thread(() => 
{ 
    mainForm = GetMainFrom(tabPage); 
}); 

mainFormThread.SetApartmentState(ApartmentState.STA); 
mainFormThread.Start(); 

を、仕事のあまりになるだろうので、私は、彼らがUIで作業するときに、物事を起動するためのMainForm内のコードを変更することはできませんが、私は簡単に一言で言えば

TIA

答えて

0

は、あなただけのUIコントロールと対話することができます1「メインスレッド」を持つことができます...各ボタンのクリックがスレッド/タスクから呼ばれるように作るか、またはすることができます。これまで期間。これを回避する方法はありません(標準コードでは、別のプロセスからフォームに描画することができますが、私はそれには入りません)。

ですから、あなたのコードをパターンを設定します。

  • バックグラウンド作業を行う方法 - これは別のスレッドで行うことができます(複数可)UIを更新し
  • メソッド - UI /メインスレッド

にアイデアビーイングを行わなければなりませんシンプルなバックグラウンド作業には時間がかかり、UIを更新するべきではありません。

MAIN UI THREADで1〜2回の実行アクションが実行されているため、これは「UIをブロックする」ために発生している動作を引き起こします。

UIをブロックすると、実際にはWindows Messageポンプがポンピングできなくなります。したがって、ウィンドウのサイズを変更したり、フォームのコントロールを更新したりするたびに、1つのコマンドがポンプのメッセージになります。それはメインスレッドで実行する必要があります。そのスレッドでデータベースに接続したり、ファイルをダウンロードしたりするなどの作業を行うと、ポンプは続行できないので、「このアプリケーションは応答していません」というメッセージが表示されます。

このように、ファイルやスレッドをダウンロードし、終了したらUIスレッドに移行し、UIを更新する必要があります。テキストボックスで終わったと言う。

2つのスレッド(バックグラウンドからバックグラウンド)に移行する方法は、begininvokeを使用することです。これは、 'invoke required'を使用することで必要となるかどうかを知ることができます。 MSDN

// This method demonstrates a pattern for making thread-safe 
 
// calls on a Windows Forms control. 
 
// 
 
// If the calling thread is different from the thread that 
 
// created the TextBox control, this method creates a 
 
// SetTextCallback and calls itself asynchronously using the 
 
// Invoke method. 
 
// 
 
// If the calling thread is the same as the thread that created 
 
// the TextBox control, the Text property is set directly. 
 

 
private void SetText(string text) 
 
{ 
 
\t // InvokeRequired required compares the thread ID of the 
 
\t // calling thread to the thread ID of the creating thread. 
 
\t // If these threads are different, it returns true. 
 
\t if (this.textBox1.InvokeRequired) 
 
\t { \t 
 
\t \t SetTextCallback d = new SetTextCallback(SetText); 
 
\t \t this.Invoke(d, new object[] { text }); 
 
\t } 
 
\t else 
 
\t { 
 
\t \t this.textBox1.Text = text; 
 
\t } 
 
}

から

これは素晴らしい記事で、あなたがする必要がどこを取得します: MSDN about thread safe code and invoke required

+0

は、あなたの完全な説明をいただき、ありがとうございます。しかし、私はちょっとあなたが説明したことのほとんどを知っていたが、私の質問には、私のコードにこのような変更を加えることをやりかける方法/ショートカットがあるかどうかが問題でした。たとえば、複数のUIスレッドを作成したり、アプリの2つのインスタンスを実行してお互いをブロックすることなく正常に動作したときの動作方法を探しています。私は多くのウィンドウを開いて、インスタンスをタブコントロールの下で管理したいと思っていません。 – Alireza

+0

複数のプロセス(基本的に複数のアプリケーションを実行している)以外は、いいえ、存在しません。あなたは根本的な設計上の問題は残念です。 「訂正する」最も簡単な方法は、タスクフレームワークを使用することです。 – adudley