本文介绍了有制作[IsOneWay = TRUE] WCF服务异步调用和使用客户端上的任务同步方法之间有显著差异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我定义一个服务:

[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服务异步调用和使用客户端上的任务同步方法之间有显著差异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 12:11