C# 我可以忽略WCF异步EndXXX调用吗?
我有2个服务为WCF呼叫提供服务。从客户端,我向两个服务发送相同的异步WCF BeginXXX调用,然后开始使用WaitHandle.waitHandles(waitHandles)等待答复,其中waitHandles是来自2个BeginXXX调用返回的IAsyncResults的waitHandles数组 我只想使用响应速度更快的服务的回复,即当WaitHandle.WaitAny返回索引时,我只调用带有相应IAsyncResult的EndXXX以获得更快的结果。我从不给另一端打电话 我这样做的原因是,有时一个服务在垃圾收集中使用了几秒钟,并且不能快速响应。根据我的经验,这两个服务通常在不同的时间进行垃圾收集,因此其中一个服务几乎总是能够快速返回答案。我的客户端应用程序非常耗时,我需要在几毫秒内得到答案 我的问题是:C# 我可以忽略WCF异步EndXXX调用吗?,c#,multithreading,performance,wcf,asynchronous,C#,Multithreading,Performance,Wcf,Asynchronous,我有2个服务为WCF呼叫提供服务。从客户端,我向两个服务发送相同的异步WCF BeginXXX调用,然后开始使用WaitHandle.waitHandles(waitHandles)等待答复,其中waitHandles是来自2个BeginXXX调用返回的IAsyncResults的waitHandles数组 我只想使用响应速度更快的服务的回复,即当WaitHandle.WaitAny返回索引时,我只调用带有相应IAsyncResult的EndXXX以获得更快的结果。我从不给另一端打电话 我这样做
取决于调用开始/结束模式的对象。有些已知泄漏。从CLR通过杰弗里·里克特的C#: 您必须调用Endxxx,否则将泄漏资源。CLR分配一些 启动异步操作时的内部资源。如果Endxxx 如果从未调用,则仅当 进程终止
BeginXXX
中指定一个回调函数,它只调用EndXXX
?这样您就可以始终调用EndXXX
并遵循框架的使用方式。您仍然可以使用等待句柄AFAIK基于任务的模式使用线程池来处理其工作。 我的客户每秒打数千个电话,完全可以 扔掉线程池 如果您使用
Task.Run
或Task.Factory.StartNew
,则情况会如此。本身,Task.Factory.fromsync
不会显式创建或切换线程
回到你的场景:
我只想使用回答更快的服务的回复,
i、 e.当WaitHandle.WaitAny返回索引时,我只调用EndXXX
使用相应的IAsyncResult以获得更快的结果。我不
有没有给对方打过电话
让我们为BeginXXX/EndXXX
异步服务调用创建Task
包装器:
public static class WcfExt
{
public static Task<object> WorkAsync(this IService service, object arg)
{
return Task.Factory.FromAsync(
(asyncCallback, asyncState) =>
service.BeginWork(arg, asyncCallback, asyncState),
(asyncResult) =>
service.EndWork(asyncResult), null);
}
}
这与:
var task = CallBothServicesAsync(service1, service2);
task.Wait();
Console.WriteLine("Result: " + task.result);
此代码将阻止当前线程,与原始场景中的WaitHandle.WaitAny
类似
现在,也不推荐使用这样的阻塞,因为这样会失去异步编程模型的优势,损害应用程序的可伸缩性。被阻止的线程可能正在做一些其他有用的工作,而不是等待,例如,在web应用程序的情况下,它可能正在服务另一个传入的客户端请求
理想情况下,您的逻辑应该是“一路异步”,直到某个根入口点。例如,使用控制台应用程序:
static async Task CoreLoopAsync(CancellationToken token)
{
using(var service1 = CreateWcfClientProxy())
using(var service2 = CreateWcfClientProxy())
{
while (true)
{
token.ThrowIfCancellationRequested();
var result = await CallBothServicesAsync("data");
Console.WriteLine("Result: " + result);
}
}
}
static void Main()
{
var cts = CancellationTokenSource(10000); // cancel in 10s
try
{
// block at the "root" level, i.e. inside Main
CoreLoopAsync(cts.Token).Wait();
}
catch (Exception ex)
{
while (ex is AggregatedException)
ex = ex.InnerException;
// report the error
Console.WriteLine(ex.Message);
}
}
您的目标框架版本是什么?也许您可以使用基于异步
Task
的模式,它将负责EndXXX
:AFAIK基于任务的模式使用线程池来处理其工作。我的客户每秒打几千个电话
var task = CallBothServicesAsync(service1, service2);
task.Wait();
Console.WriteLine("Result: " + task.result);
static async Task CoreLoopAsync(CancellationToken token)
{
using(var service1 = CreateWcfClientProxy())
using(var service2 = CreateWcfClientProxy())
{
while (true)
{
token.ThrowIfCancellationRequested();
var result = await CallBothServicesAsync("data");
Console.WriteLine("Result: " + result);
}
}
}
static void Main()
{
var cts = CancellationTokenSource(10000); // cancel in 10s
try
{
// block at the "root" level, i.e. inside Main
CoreLoopAsync(cts.Token).Wait();
}
catch (Exception ex)
{
while (ex is AggregatedException)
ex = ex.InnerException;
// report the error
Console.WriteLine(ex.Message);
}
}