【发布时间】:2023-03-26 11:34:01
【问题描述】:
我有以下 WCF 合同:
[ServiceContract(Namespace = "http://abc/Services/AdminService")]
public interface IAdminService
{
[OperationContract]
string GetServiceVersion();
// More methods here
}
GetServiceVersion 是一个返回字符串的简单方法。它用作 ping 以检查服务是否可达。
现在我想异步调用它,认为它比使用 .NET 线程在后台调用它更有效。
所以,我专门为此设计了以下界面:
[ServiceContract(Namespace = "http://abc/Services/AdminService")]
public interface IMiniAdminService
{
[OperationContract(Action = "http://abc/Services/AdminService/IAdminService/GetServiceVersion", ReplyAction = "http://abc/Services/AdminService/IAdminService/GetServiceVersionResponse")]
Task<string> GetServiceVersionAsync();
}
这使得异步调用GetServiceVersion API 成为可能:
var tmp = new ChannelFactory<IAdminService>("AdminServiceClientEndpoint");
var channelFactory = new ChannelFactory<IMiniAdminService>(tmp.Endpoint.Binding, tmp.Endpoint.Address);
var miniAdminService = channelFactory.CreateChannel();
return miniAdminService.GetServiceVersionAsync().ContinueWith(t =>
{
if (t.Exception != null)
{
// The Admin Service seems to be unavailable
}
else
{
// The Admin Service is available
}
});
代码有效。
我的问题是 - 它是否利用 IOCP 来调用延续?
一般来说,有没有办法知道是否通过 IOCP 调用了延续(如果需要,在调试器中)?
附言
这是我的异步 WCF 方法延续的堆栈跟踪:
> *** My Code *** Line 195 C#
mscorlib.dll!System.Threading.Tasks.ContinuationTaskFromResultTask<string>.InnerInvoke() + 0x111 bytes
mscorlib.dll!System.Threading.Tasks.Task.Execute() + 0x69 bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) + 0x4f bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x28d bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x47 bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) + 0x3b5 bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) + 0x104 bytes
mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x2a bytes
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x249 bytes
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x1e bytes
[Native to Managed Transition]
现在,这个堆栈跟踪看起来与我从Task.Factory.StartNew 调用的方法得到的非常相似,这确实是基于线程池的:
> *** My Code *** Line 35 C#
mscorlib.dll!System.Threading.Tasks.Task<int>.InnerInvoke() + 0x59 bytes
mscorlib.dll!System.Threading.Tasks.Task.Execute() + 0x60 bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) + 0x37 bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x1a2 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x33 bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) + 0x2ff bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) + 0xd3 bytes
mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x22 bytes
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x22e bytes
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x18 bytes
[Native to Managed Transition]
【问题讨论】:
-
请注意,您不必修改服务器以使客户端异步(并使用 IOCP)。这与问题无关,只是说。并且使用
Task.Factory.StartNew肯定不会获得 IOCP,而是会增加开销。 -
当然,但是有没有办法告诉 IOCP 驱动的延续与线程池驱动的延续?因为,在 continuation 中的堆栈跟踪看起来几乎相同。
-
我感觉延续已发布到线程池,因此它没有在前一个任务运行的线程上同步运行。尝试添加
ExecuteSynchronously并再次查看堆栈。我 99% 是肯定的,IOCP 被用于 .NET 中的所有相关网络内容。见stackoverflow.com/a/21439483/122718。
标签: c# wcf asynchronous task-parallel-library