0

i recently acquired some source code for a console wrapper for a server. The program was originaly in WPF and part of the code was:

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);
    }));
}

Its also had this annotation in both voids:

// You have to do this through the Dispatcher because this method is called by a different Thread

However in WinForms there is no such thing - is there a way to change this to a Background worker or something (Ive barely done any multi-threading)?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Alex Ogden
  • 69
  • 1
  • 1
  • 5

2 Answers2

1

Both methods are event handlers. Chances are they are from some kind of listening code and I would expect that they are called from a non UI thread (eg normally a threadpool thread that is doing the listening). You can check that by putting a break point and looking at the threads window in the debugger.
So you will need to apply the winforms way of updating the UI from a non UI thread.
If you search SO you should find quite a lot on how to do that. E.g
Updating UI from a different thread
How to update GUI from another thread in C#?

Community
  • 1
  • 1
Ricibob
  • 7,505
  • 5
  • 46
  • 65
  • Thanks, but im not too sure how i can apply this to my code - Im much better with VB.NET, still getting used to C# – Alex Ogden Apr 07 '12 at 13:08
1

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.

Brad Rem
  • 6,036
  • 2
  • 25
  • 50
  • The problem is both ServerProc methods are event handlers - and will be called by the existing code on a non UI thread. Im note sure how BackgroundWorker can help in this case? I dont think he wants to rewrite the existing server-listening/event-firing code - just the event handlers - an there are already on a non UI thread. – Ricibob Apr 07 '12 at 13:14
  • THANK YOU SO MUCH! ;D i used the Method invoker! No i can finally get this application going. Great help. Thanks. – Alex Ogden Apr 07 '12 at 13:14
  • @AlexOgden If this provided a solution for you then you should mark it as the accepted answer by clicking the tick at the left. – Ricibob Apr 08 '12 at 08:26