调用ServiceHost.Close()
允许主机实例通过允许正在进行的呼叫完成退出,同时拒绝将来的客户端呼叫。假设ServiceHost.CloseTimeout
设置为10秒,那么ServiceHost
实例将在等待Close()
返回时阻止10秒
a)如果Close()
在10秒内没有返回,会发生什么? ServiceHost
实例会强行关闭而不会抛出任何异常吗?
b)Close()
在指定时间内没有返回的常见情况是什么?也许正在处理正在进行的客户呼叫时?
谢谢
回复:
我很困惑。在您的示例中,服务主机确实等待操作完成,但在我的示例中它没有,因为Console.WriteLine("GetDog completed");
(在GetDog()
内调用)未执行:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Threading;
namespace ConsoleApplication1
{
[ServiceContract]
public interface IDogs
{
[OperationContract]
string GetDog();
}
public class Animals : IDogs
{
public string GetDog()
{
Thread.Sleep(30000);
Console.WriteLine("GetDog completed"); // this doesn't get executed
return "dalmatian";
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost host1 =
new ServiceHost(typeof(Animals),new Uri("http://localhost:8000"));
host1.AddServiceEndpoint(typeof(IDogs), new BasicHttpBinding(), "Dogs");
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
host1.Description.Behaviors.Add(behavior);
host1.AddServiceEndpoint(
typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex");
host1.Open();
Thread.Sleep(6000);
host1.Close();
}
}
BTW - 为什么在主线程(调用host.Close()
)中没有抛出异常?相反,它是从执行Service.doFoo()
的线程抛出的?!
答案 0 :(得分:1)
a)它会抛出一个TimeoutException。
b)如果您使用耗时的事情覆盖OnClosing
,OnClose(TimeSpan)
或OnClosed
,可能会超时。而且,是的,根据这个list of errors,它将等待调度操作。见SfxCloseTimedOutWaitingForDispatchToComplete
。需要测试一下。
<强>更新即可。嗯,显然,这是事实。尽管客户端连接将立即中止,但服务主机将在更改主机状态之前等待操作完成。这是我用来测试它的代码:
class Program
{
static void Main(string[] args)
{
//Server
string baseUri = "http://localhost:8080/test/";
ServiceHost host = new ServiceHost(new Service(), new Uri(baseUri));
BasicHttpBinding binding = new BasicHttpBinding();
var endpoint = host.AddServiceEndpoint(typeof(IService), binding, baseUri);
host.Closed += ((sender, arguments) => Console.WriteLine("Closed"));
host.Open();
//Client
ChannelFactory<IService> factory = new ChannelFactory<IService>(endpoint);
new Action(() =>
{
try
{
factory.CreateChannel().DoFoo();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}).BeginInvoke(null, null);
//Making sure request has reached the server
Thread.Sleep(1000);
host.Close();
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
public void DoFoo()
{
Console.WriteLine("DoFoo started");
Thread.Sleep(10000);
Console.WriteLine("DoFoo finished");
}
}
[ServiceContract]
interface IService
{
[OperationContract]
void DoFoo();
}
输出:
DoFoo started An error occurred while receiving the HTTP response to http://localhost:8080/tes t/. This could be due to the service endpoint binding not using the HTTP protoco l. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details. DoFoo finished Closed