0

I working on a WPF GUI app that acts as socket server by using TcpListener class. TcpListener is configured to make an callback when data is received to the listened socket. However the problem is that TcpListener callback comes from another thread and causes following error when I try to touch GUI from the callback:

"Cross-thread operation not valid: Control 'slider' accessed from a thread other than the thread it was created on."

Any ideas how to solve this?

I'm familiar with Qt where this would be done with signal/slot system that can send events to another threads. Is there similar functionality in C#?

TeroK
  • 103
  • 2
  • 10
  • You need to marshall the code in your call back to be executed in the UI thread for anything that might trigger a change in a UI control (in your case the slider). Depending on what your code looks like you can do this by using `Control.Invoke` or the `Dispatcher` class – Sebastian Piu Mar 31 '14 at 13:59
  • Yes, in WPF it is the `Dispatcher`. Basically it will marshal a call onto the UI message queue for processing on the UI thread. – Adam Houldsworth Mar 31 '14 at 13:59
  • The topc seems to be covered [here][1]. [1]: http://stackoverflow.com/questions/4016921/wpf-invoke-a-control – Codor Mar 31 '14 at 13:59

5 Answers5

0

You should invoke your code in UI thread. Try to use Dispatcher

Application.Current.Dispatcher.Invoke(Callback):
Alex
  • 172
  • 1
  • 6
0

You need to use the WPF Dispatcher class to invoke the method back to the UI thread - see

this

auburg
  • 1,373
  • 2
  • 12
  • 22
0

You want to use the Dispatcher.Invoke method.

If your this is DependencyObject class, you can simply use this:

this.Dispatcher.Invoke((Action)(() =>
    {
        slider.DoAnythingYouWant();
    }));
hmnzr
  • 1,390
  • 1
  • 15
  • 24
0

You cannot directly access GUI elements from a separate (e.g. pulled from the thread pool for async operations or directly created with the Thread class). What you need to do is perform your action through the dispatcher, like so:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => slider.Text = "mystuff"));

For more information on how the Dispatcher manages threading, see the MSDN link below:

http://msdn.microsoft.com/en-us/library/vstudio/system.windows.threading.dispatcher

Michael
  • 1,306
  • 1
  • 12
  • 30
  • Accessing some GUI element only wasn't what I meant. What I really wanted is to trigger my own UI thread method from another so that it acts like method was called by some button press for example. Can I use Dispactcher to do that? I.e. then I could access all UI class stuff without worrying being in wrong thread. – TeroK Mar 31 '14 at 14:42
0

Found the solution to make callback function completely in UI thread (CommandHandler is method in MainForm and called from another thread from AsynchronousSocketListener):

    void CommandHandler()
    {
        if (InvokeRequired)
        {
            /* If called from a different thread, we must use the Invoke method to marshal the call to the proper thread. */
            BeginInvoke(new AsynchronousSocketListener.ReadHandler(CommandHandler));
            return;
        }
        else
        {
            //do UI thread code here
        }
    }

For those may need working example, stuff was done this way in Basler Pylon 4.0 library example program named PylonLiveView.

TeroK
  • 103
  • 2
  • 10