2011-08-28 5 views
7

私は基本的にクライアントからの接続を待つServerクラスを持っています。そのクラスの中で、クライアントからバイトを受け取れるようにするためにNetworkStreamオブジェクトを作成します。 NetworkStream.Read()メソッドは非同期ではないため(つまり、messageboxメソッドに似たコードを実行するためにクライアントからバイトを読み取るまで待機する)、別のスレッドでバイトを読み取る必要があります。プログラムを使用しているユーザは、プログラムがデータを読み込むのを待っている場合でも、プログラムと対話することができます。異なるスレッドからのアクセスオブジェクト

とにかく、多くのオブジェクトがそのスレッドによって所有されています。 1つの例は、そのクラスにlogというListがあるということです。私はそのリストを使ってサーバーの状態を知っています。たぶん接続を聞いているのかもしれません。あるいは、おそらくステータスが「接続済み」または「切断済み」でしょう。私のような何かを行う場合

ので:

public delegate void onUpdateHandler(string newStatus); 
    public event onUpdateHandler onUpdate = delegate { }; 

私はその後、火災:

私はログが更新されたときに知りたいので
Server myServer = new Server("192.168.0.120","1300"...\\ I pass the appropite parameters in order to instantiate it 

//... 
.. then I am able to latter look at the log as 
string foo = myServer.Log[0] for example. 

、サーバ・クラスに私はイベントを作成しましたサーバークラスのイベント:

onUpdate("waitingForConnection"); 

このイベントは、次の方法で受信します。

enter image description here

が、私はnewStatusで何かをしようとする場合、私は、エラーを知らせるを得る:

System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it. 

はので、どのように私はイベントにオブジェクトを渡すことができますか?


編集

ので、私はまた私がしなければということに気づく:

enter image description here

私もエラーが出ます!

が、ときに私はのようにボタンから呼び出すことと同じことを実行します。

// SERVER IS RUNNING BEFORE CALLING THIS METHOD 
    private void button3_Click(object sender, RoutedEventArgs e) 
    { 

     listView1.Items.Add("my own string"); 

    } 

私はエラーを取得しないと!

なぜイベントにエラーが発生し、通常のボタンで呼び出すときにエラーが発生しないのですか。

答えて

12

問題は、スレッドは、例えば、スレッドの親和性を有するDependencyObjectあるListViewコントロールにアクセスするUIスレッド上でこのようなメソッドを実行するためにDispatcherを使用しようとしていることである:

Application.Current.Dispatcher.Invoke((Action)(() => 
{ 
    listView1.Items.Add(newStatus); 
})); 

も参照してください追加情報についてはthreading model referenceをご覧ください。

+0

を私の方法では、エラーが出てくる:ラムダ式がデリゲート型ではないので、 'System.Delegate'を型に変換することはできません。 –

+0

@TonoNam:ああ、キャストするか、明示的にアクションを作成する必要があります。 –

+0

@トーノ、ラムダは、いくつかのデリゲート型にキャストする必要があります、私の編集を参照してください。 – svick

1

問題は、メソッドに送信した値で何かをしようとしているということではなく、問題はその問題です。

イベントハンドラはバックグラウンドスレッドで実行されていますが、メインスレッドに属しているのでUIコントロールを使用することはできません。

あなたはトレッドを切り替える必要があるかどうかを確認するためにCheckAccessメソッドを使用することですハンドリングの通常の方法、およびメインスレッドへの作業引き渡すInvoke方法:私はその内部に配置するとき

void server_onUpdate(string newStatus) { 
    if (!listView1.Dispatcher.CheckAccess()) { 
    listView1.Dispatcher.Invoke(server_onUpdate, newStatus) 
    } else { 
    listView1.Items.Add(newStatus); 
    } 
} 
+0

タグによると、これはWinFormsではありません... –

+0

@ H.B:私はすでにそれを修正しました。 – Guffa

+0

@Guffa素敵な説明ありがとう –

関連する問題