我目前正在将客户端应用程序迁移到.NET 4.5以使用async/await.该应用程序是WCF服务的客户端,该服务目前仅提供同步服务.我现在想知道,我应该如何异步使用这种同步服务?
我使用渠道工厂连接到WCF服务,利用服务器和客户端共享的服务合同.因此,我无法使用VisualStudio中的自动生成或svcutil生成异步客户端代理.
我已经阅读了这个相关的问题,该问题是关于是否在客户端使用包装同步调用Task.Run,或者是否使用异步方法扩展服务契约.答案表明,服务器提供的"真正的"异步方法对于客户端性能更好,因为没有线程必须主动等待服务调用完成.这对我来说很有意义,这意味着同步调用应该包含在服务器端.
另一方面,Stephen Toub在这篇博客文章中一般都不赞成这样做.现在,他没有在那里提到WCF,所以我不确定这是否适用于在同一台机器上运行的库,或者它是否也适用于远程运行的东西,但是异步性的引入对它的实际影响是连接/传输.
毕竟,由于服务器实际上并不是异步工作(并且可能不会在另一个时间内工作),因此一些线程将始终必须等待:在客户端或服务器上.这同样适用于同步使用服务(当前,客户端在后台线程上等待以保持UI响应).
为了使问题更清楚,我准备了一个例子.完整项目可在此处下载.
服务器提供同步服务GetTest.这是当前存在的,并且工作同步发生的地方.一种选择是将其包装在异步方法中,例如使用Task.Run,并将该方法作为合同中的附加服务提供(需要扩展合同接口).
// currently available, synchronous service
public string GetTest() {
Thread.Sleep(2000);
return "foo";
}
// possible asynchronous wrapper around existing service
public Task<string> GetTestAsync() {
return Task.Run<string>(() => this.GetTest());
}
// ideal asynchronous service; not applicable as work is done synchronously
public async Task<string> GetTestRealAsync() {
await Task.Delay(2000);
return "foo";
} …Run Code Online (Sandbox Code Playgroud) 这可能是一个奇怪的问题,它实际上是出于我的教育目的,所以我可以在未来可能出现的场景中应用它.
我正在使用C#.
我是压力测试所以这不是生产代码.
我通过Web服务将数据上传到我的服务器.
我使用Run.Task启动服务.
在允许下一个Run.Task开始之前,我检查任务是否完成.
这是在循环内完成的.
但是,因为我使用模块化声明的Task会不会对结果产生影响?我可以声明一个本地的Task.Run变量,但我想看看我能在多大程度上得到这个问题.
如果Task.Run可以举起事件说它已经完成,那么这可能不是问题吗?
这是我的代码:
//模块声明:
private static Task webTask = Task.Run(() => { System.Windows.Forms.Application.DoEvents(); });
Run Code Online (Sandbox Code Playgroud)
//在通过计时器调用的函数中
if (webTask.IsCompleted)
{
//keep count of competed tasks
}
webTask = Task.Run(() =>
{
try
{
wcf.UploadMotionDynamicRaw(bytes); //my web service
}
catch (Exception ex)
{
//deal with error
}
);
Run Code Online (Sandbox Code Playgroud) 我想从WCF服务调用异步方法,如:
[ServiceContract]
interface IService
{
[OperationContract]
int SomeMethod(int data);
}
int SomeMethod(int data)
{
var query = ... build LINQ query;
var response = await query.ToListAsync();
return response.Length;
}
Run Code Online (Sandbox Code Playgroud)
我不想添加async到IService界面或SomeMethod方法.使用异步方法是一个内部问题,不应该在接口中反映出来.
我怎样才能做到这一点?
澄清:
我的问题是await在非async方法中使用.我不希望服务合同发生变化(客户端不一定知道是什么async),我不想将方法拆分为BeginSomeMethod和EndSomeMethod.我想要一种await 内部使用的方法.
我几乎没有编写程序问题的异步方式.我正在用一些昂贵的方法编写WCF服务,这些方法非常适合异步调用.但我对这些实现的问题是:
Task<originalType>.这将破坏服务API约定的一致性.什么是正确的方法?将服务接口设计为async Task返回方法是否更好,即使某些方法并不昂贵且实际上没有理由使其异步?