Sam*_*der 3 c# wcf multithreading asynchronous
如果我有一个定义的服务:
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IMyService
{
[OperationContract(IsOneWay = true)]
[ReceiveContextEnabled(ManualControl = true)]
void DoSomething(Message<XElement> message);
}
Run Code Online (Sandbox Code Playgroud)
我想从我的客户端异步调用它(使用不从svcutil生成的共享契约或添加服务引用)我可以这样做:
Task task = Task.Factory.StartNew(() => myService.DoSomething(message));
... some other code
task.Wait();
Run Code Online (Sandbox Code Playgroud)
我还可以将我的服务定义为异步:
[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);
}
Run Code Online (Sandbox Code Playgroud)
而是这样做
IAsyncResult result = myService.BeginDoSomething(message, null, null);
.... some other code
myService.EndDoSomething(result);
Run Code Online (Sandbox Code Playgroud)
这些方法之间是否存在显着差异?
Vla*_*hov 11
是的,线程池线程利用率存在差异.
CLR线程池分为两种类型的线程:worker和I/O(有关它们的更多信息,可以在.NET和MSDN上的工作线程和I/O线程的简单描述中找到).一般来说,线程池为每个核心提供250个工作线程和1000个I/O线程,因此您可以使用工作线程处理您的WCF服务输入,并使用I/O线程等待异步发送/接收操作完成(这是支持的)在Windows操作系统级别上通过重叠的I/O机制).
记住这一点,让我们看一下使用ThreadPool.GetAvailableThreads()方法为两种方法使用哪些线程:
int worker;
int ioCompletion;
ThreadPool.GetAvailableThreads(out worker, out ioCompletion);
Console.WriteLine("{0} worker and {1} I/O threads are available", worker, ioCompletion);
Run Code Online (Sandbox Code Playgroud)
我将仅显示客户端的线程池利用率的结果,但对于服务器端也是如此.
用于单向WCF操作的APM方法.
对于WCF合同:
[ServiceContract]
public interface IService1
{
[OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginDoSomething(int value, AsyncCallback callback, object state);
void EndDoSomething(IAsyncResult result);
}
Run Code Online (Sandbox Code Playgroud)
让我们使用下一个代码从客户端向服务器发送100个请求:
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);
}
Run Code Online (Sandbox Code Playgroud)
输出是:
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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我的x4核心机器上可以使用所有工作线程,并且正在使用多个I/O线程.
作为TPL任务运行同步单向操作.
对于WCF合同:
[ServiceContract]
public interface IService2
{
[OperationContract(IsOneWay = true)]
void DoSomething(int value);
}
Run Code Online (Sandbox Code Playgroud)
让我们使用下一个代码运行从客户端到服务器的100个请求(只是想注意TPL使用CLR ThreadPool发动机罩):
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));
}
Run Code Online (Sandbox Code Playgroud)
输出是:
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
Run Code Online (Sandbox Code Playgroud)
如您所见,现在正在使用工作线程,但不使用I/O线程.
那么,推荐的方法是什么?
总之,您的解决方案应该:
因此,推荐的方法是WCF的基于任务的异步模式,满足上述所有要求.
WCF的基于任务的异步模式.
合同:
[ServiceContract]
public interface IService3
{
[OperationContract(IsOneWay = true)]
Task DoSomethingAsync(int value);
}
Run Code Online (Sandbox Code Playgroud)
让我们再次发送100个请求:
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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2743 次 |
最近记录: |