문제

I have a form that was created on it's own UI thread running in the system tray which I need to manipulate with a signalR connection from the server which I believe to be running on a background thread. I'm aware of the need to invoke controls when not accessing them from their UI thread. I am able to manipulate (make popup in my case) using the following code that is called on form load but would like a sanity check as I'm fairly new to async:

 private void WireUpTransport()
    {
        // connect up to the signalR server
        var connection = new HubConnection("http://localhost:32957/");
        var messageHub = connection.CreateProxy("message");
        var uiThreadScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        var backgroundTask = connection.Start().ContinueWith(task =>
        {
            if (task.IsFaulted)
            {
                Console.WriteLine("There was an error opening the connection: {0}", task.Exception.GetBaseException());
            }
            else
            {
                Console.WriteLine("The connection was opened successfully");
            }
        });

        // subscribe to the servers Broadcast method
        messageHub.On<Domain.Message>("Broadcast", message =>
        {
            // do our work on the UI thread
            var uiTask = backgroundTask.ContinueWith(t =>
            {
                popupNotifier.TitleText = message.Title + ", Priority: " + message.Priority.ToString();
                popupNotifier.ContentText = message.Body;
                popupNotifier.Popup();
            }, uiThreadScheduler);
        });
    }

Does this look OK? It's working on my local machine but this has the potential to be rolled out on every user machine in our business and I need to get it right.

도움이 되었습니까?

해결책

Technically you should hook up to all notifications (using On<T>) before you Start listening. As far as your async work I'm not quite sure what you were trying to do, but for some reason your chaining the notification to your UI in On<T> to the backgroundTask variable which is the Task that was returned to you by the call to Start. There's no reason for that to be involved there.

So this is probably what you want:

private void WireUpTransport()
{
    // connect up to the signalR server
    var connection = new HubConnection("http://localhost:32957/");
    var messageHub = connection.CreateProxy("message");
    var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();

    // subscribe to the servers Broadcast method
    messageHub.On<Domain.Message>("Broadcast", message =>
    {
        // do our work on the UI thread
        Task.Factory.StartNew(
            () =>
            {
                popupNotifier.TitleText = message.Title + ", Priority: " + message.Priority.ToString();
                popupNotifier.ContentText = message.Body;
                popupNotifier.Popup();
            }, 
            CancellationToken.None,
            TaskCreationOptions.None,
            uiTaskScheduler);
    });

    connection.Start().ContinueWith(task =>
    {
        if (task.IsFaulted)
        {
            Console.WriteLine("There was an error opening the connection: {0}", task.Exception.GetBaseException());
        }
        else
        {
            Console.WriteLine("The connection was opened successfully");
        }
    });
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top