0

最近、サーバー用のコンソール ラッパーのソース コードを入手しました。プログラムは元は WPF であり、コードの一部は次のとおりです。

private void ServerProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    Dispatcher.Invoke(new Action(() =>
    {
        ConsoleTextBlock.Text += e.Data + "\r\n";
        ConsoleScroll.ScrollToEnd();
    }));
}

private void ServerProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Dispatcher.Invoke(new Action(() =>
    {
        ConsoleTextBlock.Text += e.Data + "\r\n";
        ConsoleScroll.ScrollToEnd();
        ParseServerInput(e.Data);
    }));
}

また、両方のボイドにこの注釈がありました。

// このメソッドは別のスレッドによって呼び出されるため、Dispatcher を介してこれを行う必要があります

ただし、WinForms にはそのようなものはありません。これをバックグラウンド ワーカーなどに変更する方法はありますか (マルチスレッドはほとんど実行していません)。

4

2 に答える 2

1

どちらのメソッドもイベント ハンドラです。ある種のリッスン コードからのものである可能性があり、非 UI スレッド (通常、リッスンを行っているスレッドプール スレッドなど) から呼び出されると予想されます。ブレークポイントを置き、デバッガーのスレッドウィンドウを見ることで確認できます。
そのため、非 UI スレッドから UI を更新する winforms の方法を適用する必要があります。
SO を検索すると、その方法がかなり多く見つかるはずです。例:別の
スレッドからの UI の更新
C# で別のスレッドから GUI を更新するには?

于 2012-04-07T13:04:51.933 に答える
0

Some background: A process that is running in a thread other than the UI thread is not allowed to access any UI controls directly. Your WPF ServerProc is running in a different thread than your UI which requires the Dispatcher to help you communicate from the ServerProc thread back to the UI controls in your UI thread.

If your ServerProc -- in WPF or WinForms -- were running in the UI thread, you would not need to surround it with the Dispatcher.Invoke call.

For you, you can put your ServerProc in a BackgroundWorker (MSDN example). Your DoWork method would contain the meat of the code doing the work and then depending on how the ServerProc does its work, you might be able to use ProgressChanged to do what both your sample WPF methods are doing. ProgressChanged has a parameter passed in that you would indicate if it were an error or data has been received and inside the function you could display the appropriate info. Take a look at the MSDN docs because they have a good example.

What's important to point out is that ProgressChanged happens on the UI thread so you do NOT need to surround your calls to your UI controls with Invoke; just call them normally. Same goes for RunWorkerCompleted which may be the other option for displaying data when your ServerProc has finished its job.

Finally, if you actually had to access a UI control from within your thread, you do something very similar looking as your WPF code sample. Look at MethodInvoker. Instead of Dispatcher, you're really just calling it from your main Form.

于 2012-04-07T13:05:38.720 に答える