1

I have an issue with cross threading on a UI. I have read all the ways to do it and have implemented them as seen below.

public void UpdateList(object obj)
    {
        // do we need to switch threads?
        if (listBox1.InvokeRequired)
        {
            MethodInvoker del = () => UpdateList(obj);
            this.Invoke(del);
            return;
       }
        // ok so now we're here, this means we're able to update the control
        // so we unbox the object into a string
        string text = (string)obj;
        // and update
        listBox1.Items.Add(text);
    }

The issue comes when I try to do a

hubConnection.Start().Wait();

After that call I am trying to update my list.

Without the wait is fine. When I add the Wait it hangs on the UpdateList Invoke. There is no error...it just hangs.

I am handling this call in a button event.

Jeff
  • 2,061
  • 4
  • 27
  • 45
  • hubConnection.Start().Wait() creates a deadlock on the main-thread. Remove the wait and see – lboshuizen Sep 19 '14 at 15:51
  • Easy rules to remember: using Invoke is 99% wrong, always use BeginInvoke. Starting a thread and waiting on it is 100% wrong, no need for a thread at all. Using InvokeRequired is 95% wrong, you already know it is being called from a thread. Write them down, pin it on the wall, keeps you out of trouble. – Hans Passant Sep 20 '14 at 11:48

2 Answers2

1

Wait() is creating a deadlock on the mainthread.

Replace the hubconnection.Start.Wait() with:

await hubconnection.Start() in an async method:

public void async StartHubClickedEvent(...){
   await hubconnection.Start()
}

The Microsoft Async library enables use of async/awaut on .net 4.0 and VS12.

Install-Package Microsoft.Bcl.Async

See Deadlock when thread uses dispatcher and the main thread is waiting for thread to finish

Community
  • 1
  • 1
lboshuizen
  • 2,746
  • 17
  • 20
-1

You've generated a recursive loop. Assuming an Invoke is Required, you'll call up the same method, hit if (listBox1.InvokeRequired) again (which will still pass true) and start looping as you keep calling up the same method again and again. It's better to do an If..Else pattern here where you directly invoke the change on the ListBox or simply perform the change without the invoke

An Example

    if (listBox1.InvokeRequired)
    {
        listBox1.Invoke(()=> { listBox1.Items.Add((string)text) };
    }
    else
    {
       string text = (string)obj;
       // and update
       listBox1.Items.Add(text);
    }
ChargerIIC
  • 1,620
  • 1
  • 33
  • 47
  • 2
    Calling invoke transfers execution to the main thread. When updatelist is then called the second time InvokeRequired will return false ==> End of Recursion – lboshuizen Sep 19 '14 at 16:11