bozydar.sz
bozydar.sz

Reputation: 359

WCF service freezed when created after new Control created

I have a following sample project:

namespace ConsoleApplication1
{
    [ServiceContract]
    public interface IFoo
    {
        [OperationContract]
        string GetText();
    }

    public class Foo : IFoo
    {
        public string GetText()
        {
            return "foo";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var host = new ServiceHost(typeof(Foo), new Uri("http://localhost:9995/foo")))
            {
                host.AddServiceEndpoint(typeof(IFoo), new BasicHttpBinding(), "");

                //new Control();
                host.Open();
                Console.ReadKey();
            }
        }
    }
}

Which works OK, by when I uncomment line new Control() and run the application again, the service stops to work.

Does someone know why it is happening? Why creating a new Control before calling host.Open(), stops the WCF service from working?

Note: I found out this problem after debugging a big project where some services weren't working. It appeared that the services with which there is a problem were created only after some UserControl has been created.

Upvotes: 0

Views: 123

Answers (1)

Tony
Tony

Reputation: 7445

If you opened ServiceHost instance before starting the UI thread, it will run on its own thread. Otherwise it will use the message loop (UI thread).

In your case, when a new Control is created before host is opened, wcf will use message loop. At the same time this: Console.ReadKey() blocks main thread, so your app hangs.

If you will write like this:

//Console.ReadKey();
while (true)
{
    Application.DoEvents();
    Thread.Sleep(100);
}

It will work. Try it.

For more detail infomation see here and some SO answers: WCF threading - non-responsive UI

And one more great book link with exactly (I think so) your problem.

EDIT:

When host.Open() is called WCF is checking value of SynchronizationContext.Current (see SynchronisationContext). If it is null then WCF will use new context, if it is not null WCF will use existing context.

Before you call new Control() SynchronizationContext.Current was null, after it was called SynchronizationContext.Current = WindowsFormsSynchronizationContext. This means main thread and a message loop is used, but Console.ReadKey() blocks the main thread. So app hangs.

Another solution is to write like this:

host.AddServiceEndpoint(typeof(IFoo), new BasicHttpBinding(), "");

// this will force WindowsFormsSynchronizationContext to be created
new Control();

// create new sync context, and WCF will use it, not WinForms context
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());

host.Open(); // WCF will respond
Console.ReadKey(); // main thread is blocked

Upvotes: 1

Related Questions