1

ハイパーターミナルのようなプログラムを作成しようとしていますが、シリアル ポートで回線を取得してバックグラウンドのリスト ボックスにポストするのに問題があります。以下の例では、 for ループが 100 回実行されている間にプログラム全体がフリーズし、100 行すべてが吐き出されます... 行ごとに更新したいのですが、なぜそれを行っているのかわかりません。

バックグラウンドワーカーも試してみましたが、同じことをしているようでした。

前もって感謝します...

    static System.Threading.Thread thread;
    public void button2_Click(object sender, RoutedEventArgs e)
    {
        if(Sp.IsOpen){
            stop = false;

            thread = new System.Threading.Thread(
                new System.Threading.ThreadStart(
                  delegate()
                  {
                    System.Windows.Threading.DispatcherOperation
                      dispatcherOp = listBox1.Dispatcher.BeginInvoke(
                      System.Windows.Threading.DispatcherPriority.Normal,
                      new Action(
                        delegate()
                        {
                            for(int y = 0; y <100; y++)
                            {
                                String line = Sp.ReadLine();
                                listBox1.Items.Add(line);
                            }
                        }
                               ));

              }
          ));
            thread.Start();


        }else{
            item.Content = ("No Comm Ports are Open");
            item.IsSelected = true;
            listBox1.Items.Add(item);
        }

    }
4

3 に答える 3

1

SP.ReadLineUI スレッドでコードを実行しています。

コードを 1 つの大きなコードではなく、3 つのメソッドに分割しました。

private Thread _thread;

private void Kickoff()
{
    _thread = new Thread(() => ScheduleWork(listBox1));
    thread.Start();
}

private void ScheduleWork(ListBox box)
{
    box.Dispatcher.BeginInvoke((Action)() => Fill(box));
}

private void Fill(ListBox box)
{                           
    for(int y = 0; y <100; y++)
    {
        String line = Sp.ReadLine();
        listBox1.Items.Add(line);
    }
}

この明確化されたバージョンでは、3 つの方法があります。

  1. 新しいスレッドを作成して実行するキックオフ
  2. ScheduleWorkで実行され_thread、充填をスケジュールします
  3. Fillは、実行しようとしていた作業を実際に実行します_thread

問題は、Kickoffが UI スレッドで実行され、ScheduleWorkが で実行され_threadFillが UI スレッドで実行されることです。

Dispatcher.BeginInvokeは本質的に、「このメソッドを使用して、スケジュールしたいときはいつでも UI スレッドで実行してください、kthxbai」を意味します。したがって、コードはすべて UI スレッドで実行されます

次のようなことをする必要があります

private Thread _thread;

private void Kickoff()
{
    _thread = new Thread(() => ScheduleWork(listBox1));
    thread.Start();
}

private void ScheduleWork(ListBox box)
{                  
    for(int y = 0; y <100; y++)
    {
        String line = Sp.ReadLine();
        box.Dispatcher.BeginInvoke((Action<string>)(str) => 
            listBox1.Items.Add(str),
            line);
    }
}
于 2012-11-02T21:09:16.873 に答える
0

バックグラウンドスレッドからUIを更新することはできません。これをダウイングするラインをに変更してみてください

listBox1.Dispatcher.BeginInvoke(DispatcherPriority.Render, ()=>listBox1.Items.Add(line));

スレッドの優先度を変更するには、 MSDN:DispatcherPriorityを試してみてください。

于 2012-11-02T21:03:18.100 に答える
0

あなたのスレッドがGUIスレッドよりも優先されていると思います。GUIが更新できるようにスレッドをスリープ状態にする必要があります。そうしないと、一連の更新をキューに入れ、イベントが終了してプログラムがアイドル状態になったときにそのキューを処理します。優先度を低く設定することは、おそらく良い方法ではありません。

個人的には、COM ポート ロジックをオブジェクトに移動し、それを独自のスレッドで動作させます。次に、タイマーでそのオブジェクトのプロパティをポーリングして、データを読み取る準備ができているかどうかを確認できます。

于 2012-11-02T20:40:47.870 に答える