0

I have a C# Window Forms application and a C++ DLL.

The DLL starts a thread and then sends progress updates to the C# form via a delegate. So far so good.

The problem is that when I try to write that progress to a control (e.g. TextBox), I get a:

An unhandled exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll

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

The code looks as follows:

public partial class Form1 : Form
{
    [UnmanagedFunctionPointer( CallingConvention.StdCall )]
    public delegate void ProgressCallback( int value );

    [DllImport( "DLL_Thread.dll", CallingConvention = CallingConvention.Cdecl )]
    public static extern void LoadIndex( [MarshalAs( UnmanagedType.FunctionPtr )] ProgressCallback callbackPointer_01 );

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click( object sender, EventArgs e )
    {
        ProgressCallback progressCallback =
        ( value ) =>
        {
            tb1.Text += String.Format( "Progress = {0}\n", value );
        };

        LoadIndex( progressCallback );
    }
}

What's the secret handshake here?

Thank you guys.

1 Answers1

0

Your delegate function is running in the second thread, since it's being called from there, and only the first thread (the "GUI thread") can access the GUI.

I'm a beginner with threads myself but I think the way you do something like that is having the second thread update a variable and, from the GUI thread, periodically check that variable in order to tell when the second thread has finished its work or updated its progress.

If you're using WinForms and there isn't a specific reason to use your own thread implementation, the BackgroundWorker component can be used to do that easily.

George T
  • 698
  • 9
  • 18