gpt4 book ai didi

c# - 使 [IsOneWay=true] WCF 服务异步与在客户端使用任务调用同步方法之间是否存在显着差异?

转载 作者:行者123 更新时间:2023-11-30 13:26:48 25 4
gpt4 key购买 nike

如果我有这样定义的服务:

[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IMyService
{
[OperationContract(IsOneWay = true)]
[ReceiveContextEnabled(ManualControl = true)]
void DoSomething(Message<XElement> message);
}

我想从我的客户端异步调用它(使用不是从 svcutil 生成的共享契约(Contract)或添加服务引用)我可以这样做:

Task task = Task.Factory.StartNew(() => myService.DoSomething(message));

... some other code

task.Wait();

我也可以将我的服务定义为异步的:

[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);

这些方法之间是否存在显着差异?

最佳答案

是的,Thread Pool 中存在差异线程利用率。

CLR 线程池将线程分为两种类型:worker 和 I/O(有关它们的更多信息,您可以在 Simple description of worker and I/O threads in .NETMSDN 中找到)。一般来说,线程池为每个内核提供 250 个工作线程和 1000 个 I/O 线程,因此您可以使用工作线程来处理 WCF 服务输入,并使用 I/O 线程等待异步发送/接收操作完成(支持在 Windows 操作系统级别上通过 overlapped 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);

我将只显示客户端的线程池利用率结果,但服务器端也一样。

一种 WCF 操作的 APM 方法。

对于 WCF 契约(Contract):

 [ServiceContract]
public interface IService1
{
[OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginDoSomething(int value, AsyncCallback callback, object state);

void EndDoSomething(IAsyncResult result);
}

让我们使用下一个代码从客户端向服务器发送 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);
}

输出是:

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 线程。

作为 TPL 任务运行同步单向操作。

对于 WCF 契约(Contract):

 [ServiceContract]
public interface IService2
{
[OperationContract(IsOneWay = true)]
void DoSomething(int value);
}

让我们使用下一个代码运行从客户端到服务器的 100 个请求(只是想注意 TPL 使用 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 线程。

那么,推荐的方法是什么?

总而言之,您的解决方案应该:

  • 利用线程池中的工作线程和 I/O 线程(尤其是对于高负载应用程序)来防止瓶颈;
  • 在 Task 中包装异步操作,这样您就可以获得 TPL 和新的 C# async/await 功能的所有好处;
  • 异步执行OneWay操作绝对合理(考虑到,有时 OneWay is not OneWay 实际上)。

因此,推荐的方法是 Task-based asynchronous pattern for WCF , 满足上述所有要求。

WCF 的基于任务的异步模式。

对于契约(Contract):

[ServiceContract]
public interface IService3
{
[OperationContract(IsOneWay = true)]
Task DoSomethingAsync(int value);
}

让我们再次发送 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);
}

输出:

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

关于c# - 使 [IsOneWay=true] WCF 服务异步与在客户端使用任务调用同步方法之间是否存在显着差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17322917/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com