我有以下示例项目:
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();
}
}
}
}
哪种方法正常,当我取消注释行new Control()
并再次运行应用程序时,服务将停止工作。
有人知道为什么会这样吗?为什么在调用host.Open()
之前创建新的Control会阻止WCF服务工作?
注意:在调试了一些服务不起作用的大项目后,我发现了这个问题。似乎只有在创建了一些UserControl
之后才创建出现问题的服务。
答案 0 :(得分:1)
如果在启动UI线程之前打开了ServiceHost
实例,它将在自己的线程上运行。否则它将使用消息循环(UI线程)。
在您的情况下,在打开主机之前创建新的Control时,wcf将使用消息循环。同时这个:Console.ReadKey()
阻止主线程,所以你的应用程序挂起。
如果你这样写:
//Console.ReadKey();
while (true)
{
Application.DoEvents();
Thread.Sleep(100);
}
它会起作用。试试吧。
有关详细信息,请参阅here和一些SO答案: WCF threading - non-responsive UI
还有一本很棒的书link完全(我认为是这样)你的问题。
修改强>:
调用host.Open()
时,WCF正在检查SynchronizationContext.Current
的值(请参阅SynchronisationContext)。如果它是null
,则WCF将使用新上下文,如果它不为null,则WCF将使用现有上下文。
在new Control()
SynchronizationContext.Current
被称为null
之后,SynchronizationContext.Current = WindowsFormsSynchronizationContext
Console.ReadKey()
被称为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
。这意味着使用主线程和消息循环,但{{1}}阻止主线程。所以app挂了。
另一种解决方案是这样写:
{{1}}