0

I'm trying to do this:

string Proxy = listBox3.SelectedIndex.ToString();

pretty simple right?

But in cross threading I get this error:

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

So I googled it and found this:

this.Invoke((MethodInvoker)(() => listBox3.Items.Add(Item2add)));

and tried it with this thinking it would work:

 string Proxy = listBox3.Invoke((MethodInvoker)(() => listBox3.SelectedIndex.ToString()));

but I got this error:

Additional information: Object reference not set to an instance of an object.

Greg D
  • 43,259
  • 14
  • 84
  • 117

2 Answers2

0

You might want to consider using a method to wrap the (surprisingly tricky) logic around cross thread updates and reads in winforms. I created one here: Is it appropriate to extend Control to provide consistently safe Invoke/BeginInvoke functionality?

It looks like this:

/// <summary>
/// Execute a method on the control's owning thread.
/// </summary>
/// <param name="uiElement">The control that is being updated.</param>
/// <param name="updater">The method that updates uiElement.</param>
/// <param name="forceSynchronous">True to force synchronous execution of 
/// updater.  False to allow asynchronous execution if the call is marshalled
/// from a non-GUI thread.  If the method is called on the GUI thread,
/// execution is always synchronous.</param>
public static void SafeInvoke(this Control uiElement, Action updater, bool forceSynchronous)
{
    if (uiElement == null)
    {
        throw new ArgumentNullException("uiElement");
    }

    if (uiElement.InvokeRequired)
    {
        if (forceSynchronous)
        {
            uiElement.Invoke((Action)delegate { SafeInvoke(uiElement, updater, forceSynchronous); });
        }
        else
        {
            uiElement.BeginInvoke((Action)delegate { SafeInvoke(uiElement, updater, forceSynchronous); });
        }
    }
    else
    {
        if (!uiElement.IsHandleCreated)
        {
            // Do nothing if the handle isn't created already.  The user's responsible
            // for ensuring that the handle they give us exists.
            return;
        }

        if (uiElement.IsDisposed)
        {
            throw new ObjectDisposedException("Control is already disposed.");
        }

        updater();
    }
}
Community
  • 1
  • 1
Greg D
  • 43,259
  • 14
  • 84
  • 117
  • This is all a little over my head... How would i use this ? just by simply doing this? `SafeInvoke(string Proxy = listBox3.SelectedIndex.ToString());` – Richard Cornish Jun 23 '15 at 19:22
  • It's an extension method, so more like this: `string myIndex; listBox3.SafeInvoke(() => myIndex = listbox3.SelectedIndex.ToString(), true);` Be sure to set forceAsynchronous to true because you're reading out of the UI. If you were setting something in the UI, it could be false. Also, it's a little weird to be turning the index into a string. I'd read it out as the scalar (int, long, I forget what it is), and convert it on the background thread as necessary. – Greg D Jun 23 '15 at 19:30
  • didn't work got this error `There is no argument given that corresponds to the required formal parameter forceSynchronous of 'Form1.SafeInvoke(Control, Action, bool)` – Richard Cornish Jun 24 '15 at 04:31
  • You must specify a boolean value for the final parameter of SafeInvoke. – Greg D Jun 25 '15 at 06:05
  • Not sure why this was downvoted. Although it's a bit much I think for his simple case, if someone was to need to update multiple controls this extension method would come in handy. – Cory Jun 25 '15 at 18:30
0

First off, that code there shouldn't even let you compile. It wouldn't let you implicitly cast from an Object to a String.

THE ONLY WAY I could see this producing this error is if listBox3 doesn't exist on the thread you're calling this from. Make sure you're calling it from the UI thread (assuming this is where your listBox is).

Try this code and see if it helps:

string Proxy; 
listBox3.Invoke((MethodInvoker)(() => Proxy = listBox3.SelectedIndex.ToString()));
Cory
  • 1,794
  • 12
  • 21