0

I have this method what called from an Async method

private void SocketConnected(Object sender, EventArgs e) {
    //Some code


    connectedLabel.Content = "Connected";
}

And the connectedLabel.Content = "Connected"; throws an error. How can I update this from this method? I've seen a few post saying use Invoke, however, that gives me an error that label doesn't have a Invoke method.

EDIT:

From looking at Dispatcher as mentioned in the comments I've got this which works.

    private string message;
    public void UpdateConnected()
    {
        connectedLabel.Content = message;
    }

    private void SocketConnected(Object sender, EventArgs e) {
        //Some stuff

        message = "Connected";
        this.Dispatcher.BeginInvoke(new Action(this.UpdateConnected), DispatcherPriority.Background);
    }

Is that the correct usage of the Dispatcher?

TMH
  • 6,096
  • 7
  • 51
  • 88
  • Can you show us how you're calling this? If you're calling it from an `async` method.. you should be `await`'ing a result.. – Simon Whitehead Feb 26 '14 at 22:06
  • 2
    What UI toolkit are you using? What `Invoke`-like method to use depends on the UI toolkits as e.g. WinForms and WPF provide different means of synchronizing oneself back into the UI thread. Add an appropriate tag, please. – O. R. Mapper Feb 26 '14 at 22:06
  • 1
    @SimonWhitehead This is using event based asynchrony, not task based asynchrony. – Servy Feb 26 '14 at 22:07
  • Oh, so it is (you would think the method signature would make me realise that). My mistake. – Simon Whitehead Feb 26 '14 at 22:08
  • Dispatcher.Invoke should fix your problem – AD.Net Feb 26 '14 at 22:08
  • I don't have the Async code, I'm using a WebSocket library which has `ws.ConnectAsync();`, and when it connects that above method is called. If I use `ws.Connect();` I don't get the error so I can only assume it's to do with the Async part. – TMH Feb 26 '14 at 22:08
  • 1
    @TomHart It's still important for us to know what UI framework you're using. – Servy Feb 26 '14 at 22:09
  • @AD.Net: [`Dispatcher`](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher%28v=vs.110%29.aspx) was only introduced with WPF, and we don't know whether the OP is using WPF yet (even though the label having a `Content` property makes this likely). – O. R. Mapper Feb 26 '14 at 22:10
  • Sorry I'm new to C#, how do I know what Framework I'm using? I'm using .NET 4.5 and my main class is `MainWindow : Window`, I don't know if that helps at all. – TMH Feb 26 '14 at 22:11
  • I've updated my question now, am I now going along the right lines? – TMH Feb 26 '14 at 22:17
  • @TomHart Would you mark some of the replies as answer? – Mikko Viitala Mar 03 '14 at 15:39
  • Sorry I forgot, SO wouldn't let me when I posted this. Done it now – TMH Mar 03 '14 at 15:59

3 Answers3

1

You can create an extension method and use async/await

await socket.ConnectTaskAsync(host,port);
connectedLabel.Content = "Connected";

public static class SocketExtensions
{
    public static Task ConnectTaskAsync(this Socket socket, string host, int port)
    {
        return Task.Factory.FromAsync(
                         socket.BeginConnect(host, port, null, null),
                         socket.EndConnect);
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
  • The OP appears to be using an event based asynchronous model, which won't work with `FromAsync`. – Servy Feb 26 '14 at 22:09
1

Regarding your edit, unless you have a need for the async method to carry on with whatever it has left to do before the label is updated, you can just use Dispatcher.Invoke rather than Dispatcher.BeginInvoke.

If you're interested in the difference: Dispatcher Invoke(...) vs BeginInvoke(...) confusion

Community
  • 1
  • 1
thudbutt
  • 1,481
  • 1
  • 19
  • 32
0

Why not just... ?

// WPF
Dispatcher.BeginInvoke(new Action(() => label.Content = "my label"));

or

// WinForms
BeginInvoke(new Action(() => label.Text = "my label"));
Mikko Viitala
  • 8,344
  • 4
  • 37
  • 62