2016-04-17 19 views
0

現在、ネットワークストリーミングソースに基づいてリストボックスを継続的に更新しようとしているWPFプロジェクトに取り組んでいます。スレッドを回避するためにWPF MainWindowメソッドを終了させる方法はありますか?

initializeComponent()メソッドは、MainWindow()メソッドが終了すると、実際にはWPFウィンドウしか表示されません。しかし、サーバーからの更新信号を継続的にリッスンし、適切な値でリストボックスを更新するために、while(true)ループを内部に入れようとしています。

それぞれのメソッドは正常に動作していますが、それはwhileループのために現在のフォームでWPFウィンドウを開かないということだけです。リストボックスのスレッド "所有権"をスレッドに渡すために機能を実装する必要があることを認識しているので、リストボックスを更新するためにバックグラウンド更新スレッドを使用しないようにしようとしています。これを行う方法について確かめてください。

必要な機能を実現するために、欠落していることが判明していますか?次のように

コードは次のとおり

public MainWindow() 
{ 
    TcpClient client = new TcpClient(); 
    client.Connect(serverAddress, port); 
    NetworkStream stream = client.GetStream(); 

    numberOfPumps = 0; //initialize as 0 on startup. 

    handshake(stream);    

    InitializeComponent(); 

    updatePumpList(stream); 
    updateListBox(); 

    while(true) 
    { 

     updatePumpList(stream); 
     updateListBox(); 
    }   
} 

updateListBox()方法は、単に辞書からリストボックスに項目を追加しています。

private void updateListBox() 
{ 
    foreach(KeyValuePair<string, PumpItem> kvp in pumpDict) 
    { 
     pumpListBox.Items.Add(kvp.Key + ": " + kvp.Value.state); 
    } 
} 
+0

コンストラクタ内で、アプリケーションのループを実行するには、一般的に良いアイデアではありません。この時点では、コントロールが完全にセットアップされていないため、何か例外がスローされた場合はおそらく骨が折れるでしょう。バックグラウンドプロセスに対応してコントロールを更新することはそれほど困難ではありません。 UIコントロールの 'Dispatcher.Invoke'メソッドを探します。 –

+0

@ChrisRydingもちろん、MainWindow()はMainWindowクラスインスタンスのコンストラクタです。明らかに、メインメソッドのようなコンストラクタを扱うことは、クラスが決して...まあ...コンストラクタ(このケースでは無限の間)であるという恐ろしい考えです。この実現に役立つことに感謝します。 – James

答えて

1

残念ながら、あなたが望むようにすることはできません。 Windowsアプリケーションでは、メイン(UI)スレッドを実行させる必要があります。そのスレッドで行っているループは、終了するまでアプリケーション全体を停止させます。ウィンドウが開いている場合は、ウィンドウがフリーズしているように見えます(ウィンドウが固定されているため)。まだ起動していなければ、永久に待機カーソルのように見えます。それのまわりには道がない。スレッドは、入力を処理したり、ウィンドウを更新するために単独で放置されなければならない。メッセージループを手動でポンピングしても(誰かがMFCを覚えている?)、貧弱な方法である。デザイナーが意図したようにメインスレッドを残しておくと、Windowsアプリケーションが最も効果的です。

もちろん、メインスレッドでは多くのことをやっていますが、ユーザーが待ち時間に気づく前に、すぐに制御できる素早いものです。同期インターネットへのアクセスは決して迅速ではなく、プロセスの寿命の間続くポーリングループは問題になりません。

ここでは2つのオプションがあります。どちらも実際にはかなり陽極です。

DispatchTimerを非同期インターネットアクセスで使用できます。

もう1つは、回避しようとしているワーカースレッドです。彼らはそれほど悪くはありません。プログラムのシャットダウンを中止するためにThreadオブジェクトへの参照を保持しておけば、UIはUIに触れるすべての操作(PropertyChangedイベントを発生させるプロパティの設定を含む)を行うときにUIスレッドを「呼び出す」必要があります。

全然大したことではないのです。

Action act =() => Status = newStatus; 
App.Current.Dispatcher.Invoke(act); 
+0

私はこれに近づいていますが、あなたは正しいと思われ、弾丸を噛んでワーカースレッドを使用する必要があります。 – James

+1

私はこれを調べて、それが最良の方法であることを確認することができます。現在の反復では、バックグラウンドワーカーを使用しています。バックグラウンドワーカーは、軽量の背景スレッドであり、必要に応じて機能しているようです。この回答に関しては、Invokeを使用してUIを更新するためにスレッドを使って作業するのが最善であるという点ではお金の価値があります。 – James

0

を使用すると、WPFウィンドウが表示されたらトリガするあなたのWPFウィンドウのonLoadイベントハンドラを設定すると考えたことがありますか?イベントハンドラは、それに応じてwhileループを実行できます。

また、コンストラクタが終了してから数分後にイベントを発生させるようにtimerを設定すると、ウィンドウを表示してからwhileループを開始することができます。

+0

UIスレッドがイベントハンドラのwhileループで永続的にブロックしている場合は、UIを更新できますか? –

関連する問題