问题描述
如果我定义一个服务:
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IMyService
{
[OperationContract(IsOneWay = true)]
[ReceiveContextEnabled(ManualControl = true)]
void DoSomething(Message<XElement> message);
}
和我想从我的客户(使用共享合同不是从SvcUtil工具生成或添加服务引用)asyncronously调用它,我可以做的:
and I want to call it asyncronously from my client (using shared contracts not generating from svcutil or add service reference) I can do:
Task task = Task.Factory.StartNew(() => myService.DoSomething(message));
... some other code
task.Wait();
我也可以定义我的服务是异步:
I could also define my service to be async:
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface ICacheKeyExchangeAsync
{
[OperationContract(IsOneWay = true, AsyncPattern = true)]
[ReceiveContextEnabled(ManualControl = true)]
IAsyncResult BeginDoSomething(Message<XElement> message, AsyncCallback callback, object state);
void EndDoSomething(IAsyncResult result);
}
和做到这一点,而不是
IAsyncResult result = myService.BeginDoSomething(message, null, null);
.... some other code
myService.EndDoSomething(result);
是否有方法之间的差异显著?
Are there significant differences between the approaches?
推荐答案
是的,有在的线程利用率。
Yes, there are a differences in Thread Pool threads utilization.
CLR线程池splitts两种类型的线程:工人和I / O(更多相关信息,您可以在Simple工人的描述和.NET 和的)。一般来说,线程池给你每个内核250工作线程和1000 I / O线程,因此您可以使用工作线程来处理WCF服务输入,I / O线程等待异步发送/接收操作完成(这是支持由机制)。
CLR thread pool splitts threads on two types: worker and I/O (more information about them you can find in Simple description of worker and I/O threads in .NET and on MSDN). Generally speaking, thread pool gives you 250 worker threads per core and 1000 I/O threads, so you can use worker threads to process your WCF service input, and I/O threads to wait for asynchronous send/receive operation completion (which is supported on Windows OS level by overlapped I/O mechanism).
以上保持头脑中,让我们通过使用线程正在利用这两种方法在一看ThreadPool.GetAvailableThreads()方法:
Keeping above in mind, let's have a look which threads are being utilized for both approaches by using ThreadPool.GetAvailableThreads() method:
int worker;
int ioCompletion;
ThreadPool.GetAvailableThreads(out worker, out ioCompletion);
Console.WriteLine("{0} worker and {1} I/O threads are available", worker, ioCompletion);
我将只显示线程池利用率客户端的结果,但它的服务器端一样好。
I'll just show results of Thread Pool utilization for client side, but it's the same for server side as well.
单程WCF操作的 APM的方法。
有关WCF合同:
[ServiceContract]
public interface IService1
{
[OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginDoSomething(int value, AsyncCallback callback, object state);
void EndDoSomething(IAsyncResult result);
}
让使用next code发送从客户100请求到服务器的:
Lets send 100 requests from client to server using next code:
ChannelFactory<IService1> channelFactory = new ChannelFactory<IService1>();
var client = channelFactory.CreateChannel();
for (int i = 0; i < 100; i++)
{
int worker;
int ioCompletion;
ThreadPool.GetAvailableThreads(out worker, out ioCompletion);
Console.WriteLine("{0} worker and {1} I/O threads are available", worker, ioCompletion);
client.BeginDoSomething(i, asyncCallback, null);
}
输出是:
1023 worker and 1000 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 996 I/O threads are available
1023 worker and 996 I/O threads are available
1023 worker and 996 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
正如你可以看到所有的工作线程可我X4的核心机和多个I / O线程正在被使用。
As you can see all worker threads are available on my x4 core machine and several I/O threads are being utilized.
运行同步单向操作TPL任务。
有关WCF合同:
[ServiceContract]
public interface IService2
{
[OperationContract(IsOneWay = true)]
void DoSomething(int value);
}
让我们使用next code运行从客户100个请求服务器(只是要注意到,TPL使用CLR线程池引擎盖下):
Let's run 100 requests from client to server using next code (just want to notice that TPL uses CLR ThreadPool underhood):
for (int i = 0; i < 100; i++)
{
int worker;
int ioCompletion;
ThreadPool.GetAvailableThreads(out worker, out ioCompletion);
Console.WriteLine("{0} worker and {1} I/O threads are available", worker, ioCompletion);
Task.Run(() => client.DoSomething(i));
}
输出是:
1023 worker and 1000 I/O threads are available
1022 worker and 1000 I/O threads are available
1021 worker and 1000 I/O threads are available
1020 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
1019 worker and 1000 I/O threads are available
正如你可以看到,现在正在利用工作线程,而不是I / O线程。
As you can see, now worker threads are being utilized, but not I/O threads.
那么,有什么建议的方法?
作为总结,你的解决方案应该:
As summary, your solution should:
- 利用工人和I /线程池O线程(特别是,对于highlyloaded应用程序),以prevent瓶颈;
- 在任务裹异步操作,这样你就可以得到TPL和新的C#异步的所有优点/等待功能;
- 这是绝对合理的异步执行单向操作
(考虑,有时OneWay是不是单向实际上)。
- Utilize worker and I/O threads from thread pool (especially, for highlyloaded applications) to prevent bottlenecks;
- Wrap asynchronous operation in Task, so you can get all benefits of TPL and new C# async/await features;
- It's absolutely reasonable to execute OneWay operation asynchronously(considering, sometimes OneWay is not OneWay actually).
因此,推荐的方法是为WCF 异步模式,即满足所有要求以上。
So, recommended approach is Task-based asynchronous pattern for WCF, that satisfies all requirements above.
有关WCF的基于任务的异步模式。
有关合同:
[ServiceContract]
public interface IService3
{
[OperationContract(IsOneWay = true)]
Task DoSomethingAsync(int value);
}
让我们再次发送100个请求:
Lets send 100 requests again:
for (int i = 0; i < 100; i++)
{
int worker;
int ioCompletion;
ThreadPool.GetAvailableThreads(out worker, out ioCompletion);
Console.WriteLine("{0} worker and {1} I/O threads are available", worker, ioCompletion);
client.DoSomethingAsync(i);
}
输出:
1023 worker and 1000 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
1023 worker and 998 I/O threads are available
1023 worker and 999 I/O threads are available
这篇关于有制作[IsOneWay = TRUE] WCF服务异步调用和使用客户端上的任务同步方法之间有显著差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!