我们有Windows服务,它从MSMQ读取消息并逐个处理。为了提高性能/吞吐量,我们转向了TPL。我们在处理消息时有几个数据库调用和WCF调用。我们观察到,在进行WCF呼叫时,前几次呼叫速度更快,但后续呼叫需要更长时间。这是示例代码。
public class TestWcf
{
public void Process(string option)
{
// container for perellel tasks and WaitAll after 50 count
TaskContainer batch = new TaskContainer(50, true);
for (int i = 1; i <= 100; i++)
{
if(option.Equals("s"))
{
batch.Add(ProcessMessage);
}
else
{
batch.Add(ProcessMessageAsync);
}
}
}
public void ProcessMessage()
{
Stopwatch sw = Stopwatch.StartNew();
PostingServiceClient client = new PostingServiceClient();
client.UpdateArchiveStatus(Guid.Parse("B6D5C77C-330A-4B00-96BF-E91A2B5970E3"),"1234567890");
sw.Stop();
Console.WriteLine("Thread {0}, Elapsed Time: {1} s", Thread.CurrentThread.ManagedThreadId, sw.Elapsed.Seconds);
//client.Close();
}
public void ProcessMessageAsync()
{
Stopwatch sw = Stopwatch.StartNew();
PostingServiceClient client = new PostingServiceClient();
var task = Task.Factory.FromAsync(
client.BeginUpdateArchiveStatus(Guid.Parse("B6D5C77C-330A-4B00-96BF-E91A2B5970E3"), "1234567890", null,
null), client.EndUpdateArchiveStatus);
task.Wait();
sw.Stop();
Console.WriteLine("Thread {0}, Elapsed Time: {1} s", Thread.CurrentThread.ManagedThreadId, sw.Elapsed.Seconds);
//client.Close();
}
}
我们正在使用外部团队WCF,它托管在IIS服务器,App Pool中,目标是.Net 2.0。 WCF服务端,serviceThrottling为500,服务合同上没有定义ServiceBehavior属性。我们在同一时间运行程序,两个控制台实例一个带有Sync选项,第二个带有Async选项。同步选项完成比Async选项快得多。我的假设是,系统不会在执行异步操作时从ThreadPool释放任务。问题是,哪种方法更好(同步与异步WCF调用)或在这种情况下是否有任何不同的方法来处理WCF调用。
答案 0 :(得分:0)
在我进入任何事情之前,您使用的是什么框架用于Windows服务? .Net 4.5(或更高版本)或.Net 4.0?
我问的原因是因为如果你有async/await
(你需要.Net 4.5。对于 1 )那么它可以大大改变代码的简单性。
现在让我们开始做生意吧。所以你正在做的事情有些不一致。
TaskContainer
到底是什么?我找不到任何文件。
此代码块
var task = Task.Factory.FromAsync(
client.BeginUpdateArchiveStatus(Guid.Parse("B6D5C77C-330A- 4B00-96BF-E91A2B5970E3"),"1234567890", null, null),
client.EndUpdateArchiveStatus);
task.Wait();
NOT 异步。
由于task.Wait()
调用,它是同步的,使用任务。使用Task
会产生一定的开销,但在大多数情况下,异步和可伸缩性的好处将超过这个小开销。这一小部分开销要比阻止呼叫或阻止线程进行网络呼叫更好。
如果你想要一个真正的异步调用,你需要这样的东西:
var guid = Guid.Parse("B6D5C77C-330A-4B00-96BF-E91A2B5970E3");
// Since I don't have a copy of the operation contract,
// I can't tell if the client call returns a specific type,
// so I'm going to assume it's `void`
var task = Task.Factory.FromAsync(client.BeginUpdateArchiveStatus, client.EndUpdateArchiveStatus, guid, null);
// If you're using .Net 4.5 or higher
// Another side note is that you'll want to return `async Task` instead of `async void` if you decide/can use `await`
await task;
sw.Stop();
// If you're not using .Net 4.0
task.ContinueWith(t =>
{
sw.Stop();
// Whatever code you want to execute now.
});
解决您的假设:
与真正异步调用一起使用时,我的假设是,系统在执行异步操作时不会从ThreadPool释放任务。
Task.Factory.FromAsync不会阻止ThreadPool线程。 (有很多资源可以验证这一点,但here's是我很快就提出来的。)
问题是,哪种方法更好(同步与异步WCF调用)或在这种情况下是否有任何不同的方法来处理WCF调用。
最好的办法是正确实施异步任务。
[1]:如果你有VS 2012或更高版本,你可以拉入NuGet包Microsoft.Bcl.Async
并为.Net 4.0解决这个问题。
编辑:我刚刚意识到我遇到了一个超过1年的问题。哎呀!这就是我在略读未解答的问题时所得到的。