none
ServiceHost.BeginOpen blocks the caller thread RRS feed

  • Question

  • I use the ServiceHost in a WPF application. When I call the ServiceHost.Open method it takes about 30 seconds to complete (I connect to a Azure ServiceBus. The long wait time seems to come from our company internet proxy).

    Because it takes that long I would like that this call does not block the Dispatcher thread and it should support Cancellation. Unfortunately, the ServiceHost does not support the Task API but it is easy to create one:

    public static class CommunicationObjectExtensions
    {
        public static Task OpenAsync(this CommunicationObject co, CancellationToken token)
        {
            token.Register(() => co.Abort());
    
            return Task.Factory.FromAsync(co.BeginOpen(null, null), co.EndOpen);
        }
    }

    Why does the ServiceHost.BeginOpen call block the Dispatcher thread? The MSDN documentation says the BeginOpen will be done asynchronously. This way the Dispatcher thread should not be blocked.

    Thursday, August 1, 2013 6:31 AM

All replies

  • Hi omjbe,

    ServiceHost.Open is a synchronous method. It will block the current thread.

    You mean that you want to wait for it to complete on another thread. if so,ManualResetEvent helps to wait for another thread.Also it looks like you're trying to host the service in Windows Forms. This is not recommended unless the service is extremely simple. You should host complex services in IIS, Windows Service, or at least a console application that does nothing other than hosting the service.

    Thanks.



    • Edited by dns jinung Thursday, August 8, 2013 7:45 AM wtite
    Friday, August 2, 2013 10:30 AM
  • Hi omjbe,

    Use System.Threading.Mutex or the lock statement can fix this issue.

    Regards,

    Thursday, August 8, 2013 8:33 AM
  • Thanks for the answers. Maybe I need to provide more information about my issue:

    1.    I’m using a WPF application to host the service. The requirements do not allow me to use IIS, WAS or something else. But the service is quite simple.

    2.    I’m using the ServiceHost.BeginOpen method instead of Open. BeginOpen should not block the UI (Dispatcher) thread. But it does block it. My suspicion is that the implementation from Microsoft has a bug.

    3.    Maybe the issue is connected with the NetTcpRelayBinding. Because with other bindings I have not seen this behaviour. I have just implemented the example described on MSDN in a WPF application and changed Open with BeginOpen: http://www.windowsazure.com/en-us/develop/net/how-to-guides/service-bus-relay/

    4.    The code snippet provided in my questions shows how to convert the asynchronous BeginOpen and EndOpen methods into a Task API.

    Friday, August 9, 2013 2:43 PM
  • Hi omjbe,

    For the BeginXXX async method, the .NET runtime should dispatch it to a thread pool thread so as not to block the main UI thread. Also, your test code is converting the Begin/End async pattern to Task based async API, have you tried directly invoking the BeginXXX method and use callback +EndXXX method style to see if it will still block the main thread?


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by omjbe Wednesday, September 4, 2013 1:31 PM
    • Unmarked as answer by omjbe Thursday, September 5, 2013 5:57 AM
    Monday, August 12, 2013 10:58 AM
    Moderator
  • Hi,

    Perhaps you can try Steven suggestion. Also here is more bigger sample code that also implement async.

    http://code.msdn.microsoft.com/windowsazure/Windows-Azure-Inter-Role-9935c439


    Regards,
    Christian HL
    Microsoft Online Community Support


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.

    Tuesday, August 13, 2013 1:50 AM
  • Hi Steven,

    I have tried it with directly invoking the BeginOpen and EndOpen method and it blocks the UI thread as well. It does not seem to be connected with the ServiceHost because the IChannelClient proxy has the same issue.

    The code below shows the WPF sample client implementation. The BeginOpen operations takes about 10 to 20 seconds. In this time the WPF window is frozen.

    private void CalculateClick(object sender, RoutedEventArgs e)
    {
        var cf = new ChannelFactory<IProblemSolverChannel>(new NetTcpRelayBinding(), 
            new EndpointAddress(ServiceBusEnvironment.CreateServiceUri("sb", "**namespace**", "solver")));
        cf.Endpoint.Behaviors.Add(new TransportClientEndpointBehavior { TokenProvider = 
            TokenProvider.CreateSharedSecretTokenProvider("owner", "**secred**") });
    
        var ch = cf.CreateChannel();
        ch.BeginOpen(OpenCallback, ch);
    }
    
    private void OpenCallback(IAsyncResult ar)
    {
        var ch = (IProblemSolverChannel)ar.AsyncState;
        ch.EndOpen(ar);
        int result = ch.AddNumbers(4, 5);
        ch.Dispose();
    
        // Callback runs in an own thread, Dispatcher.Invode is necessary
        Dispatcher.InvokeAsync(() => resultBox.Text = result.ToString());
    }

    Tuesday, August 13, 2013 6:59 AM
  • I have created a bug entry at Microsoft Connect:

    Azure ServiceBus Binding blocks the main thread

    Wednesday, September 4, 2013 1:35 PM