2011-12-27 26 views
-1

スレッドとスレッドの優先順位を扱う次のプログラムで作業しています。C#Null参照例外

私はリッチテキストボックス(DisplayTextBox)と2つのボタン(アプリケーションを実行するためのStartButtonとアプリケーションを閉じるためのExitButton)を含むウィンドウフォームを構築しました。

フォームで、私はいくつかのスレッドを作成し、それらを次々に実行しています。各スレッドで使用されるメソッドは、Threadingクラスにあります。問題のメソッドはPrintOnScreen()です。

このメソッドでは、スレッド名と優先度をStringBuilder型のstrに追加しています。次に、DisplayTextBox(Form.csにあります)にstrの内容を表示します。

しかし、「NullReferenceExceptionが未処理です:オブジェクト参照がオブジェクトのインスタンスに設定されていません」というエラーが発生しています。エラーが発生する行は次のとおりです。

DisplayTextBox.Text = Convert.ToString(str);

このエラーを解決するのに手伝ってもらえますか?ありがとう。あなたの助けのためのすべての

編集

感謝。この問題を解決するために、PrintOnScreenメソッドをForm.csクラスにコピーし、Threading.csを破棄しました。

後でAnandによって与えられたコードを使用し、それをt2.Join()の下に置きました。今は魅力のように機能します。

+0

どのオブジェクトがヌルであるか知っていますか?この質問には2つの可能な答えがあります。最初は** DisplayTextBoxです。** 2番目は** str **です。もちろん、フォーム上のDisplayTextBoxへの参照をどこに渡すか分かりません。スレッディングはForm1を継承しますが、Form1のコントロールへの参照があるわけではありません。 –

+0

コードを修正して** DisplayTextBox **への参照を渡しても、メインのUIスレッド以外の別のスレッドでコントロールを変更できないため、テキストの変更を呼び出す必要があります。 –

+0

複数のスレッドからアクセスするデータへのアクセスを実際に同期することを検討する必要があります。たとえば、両方のスレッドを同じStringBuilderインスタンスに書き込んで、Threadsコレクションを繰り返し処理しているとします。 – Jan

答えて

3

問題は、フォームのコンストラクタで発生します。 DisplayTextを再度ローカルメンバーとして宣言すると、フォームのフィールドは初期化されません。コンストラクタを次のように変更します。

private void Form1_Load(object sender, EventArgs e) 
{ 
    DescTextBox.Visible = false; 
    DisplayTextBox = new RichTextBox(); 
    DisplayTextBox.Location = new Point(15, 31); 
    DisplayTextBox.Height = 258; 
    DisplayTextBox.Width = 303; 
    panel1.Controls.Add(DisplayTextBox); 
} 

期待どおりに動作するはずです。

編集:ただし、バックグラウンドワーカースレッドからUI要素を変更する場合は、問題が発生する場合があります。そのような場合は、invokeパターンを使用する必要があります。

1

メインアプリケーションのスレッド以外のスレッドのコントロールと通信することはできません。このためにディスパーザーを使用する必要があります。ここを見て:http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.aspx

EDIT
@Fischermaenを - あわや、このことを気付かなかったが、それはまだので、彼はそれが失敗した書いたラインの動作しません。彼はまだ非メインスレッドからの制御

EDIT 2つの
関連スレッドでTextプロパティを設定するために、ディスパッチャを使用する必要があります。
How to update the GUI from another thread in C#?
In WinForms, why can't you update UI controls from other threads?

+0

ディスパッチャに関するご意見ありがとうございます。私はそれを試し、それが動作するかどうかを知らせます。みんなに感謝:) – Joe

1

私は、単純なコンソールアプリケーションでこれを試してみましたそれはうまくいった。 問題はDisplayTextBoxにあります。任意のコントロールと対話したい場合は、UIスレッドまたはDispatcherを使用する必要があります。 は 代わりに使用

DisplayTextBox.Text = Convert.ToString(str); 

のこの1

Dispatcher.Invoke(DispatcherPriority.Normal, 
        new Action(
      delegate() 
      { 
       DisplayTextBox.Text = Convert.ToString(str); 
      } 
     )); 
+0

正確に。コンソールアプリケーションでは、正常に動作します。私に与える問題は、Windowsアプリケーションに変換しようとするときです。 – Joe

+0

上記のコードを試してください。それは正常に動作するはずです。 – Anand

+0

私はコードを貼り付け、それは私にエラーを与えています - 名前 'ディスパッチャー'は現在のコンテキストに存在しません。 – Joe

0

あの、あなたのスレッドクラスに次のコードを使用します。 ここからは見ることはできませんが、問題が発生している理由の1つは、カプセル化が不十分で、コードの寿命管理が不十分であることです。

PrintOnScreenメソッド内でstrをインスタンス化すると、より良い名前を付けることができます。メンバー変数にする必要はありません。パブリックにする必要はありません。代わりにボイド結果を持っていることの

、それは

例えば、文字列の結果を返してい

SomeTextBox = PrintOnScreen(); // (GetThreadDetails might be a better name...) 

ヒントとして、プレゼンテーションとロジックを混在させないでください。 UIコントロールは、所有しているものの中で徹底的に管理してください。

そして

public SomeType SomeName; 

が財産にし、それはそれは短い形式だ場合でも、getterとsetter与えないでください

公共SomeTypeのsomenameの{取得します。セット;}

をコードする任意の他のビットは、複数の所有者を持っている必要があり

Form1.SomeType = (SomeOtherType)someVar; // with appaling consequences. 

何ものような、本当に愚かな何かを行うことができ、他のどのパスが台無しにつながります。

PS str.ToString()はConvert.ToString(str)よりも優れたオプションです。

0

これは、私が達成しようとしていることはあまり明確ではありませんが、基本フォームのThreadingクラスは、コントロールにアクセスしようとしているときに読み込まれないことを継承しています)また、これは、あなたのスレッドが表示されていない非表示のフォームに出力されるため、Form1自体に何も表示されない理由です。

あなたはSOReaderによって提起されたスレッドアクセスの問題を解決しようとしていると思います。これはこれを行う適切な方法ではありません。