我有一个服务客户端调用的WCF服务。我想使用async / await构造来包装对此的调用;但是,服务和服务客户端是.NET3.5。我对此的解决方案如下:
private async Task<ObservableCollection<MyEntity>> LoadData(ParamData param)
{
ServiceClient svc = new ServiceClient();
int results = 0;
// Set-up parameters
myParams = BuildParams(param);
// Call a count function to see how much data we're talking about
// This call should be relatively quick
var counter = Task.Factory.StartNew(() =>
{
results = svc.GetResultCount(myParams);
}).ContinueWith((task) =>
{
if (results <= 10000 ||
(MessageBox.Show("More than 10000 results, still retrieve data?"), MessageBoxButton.YesNo) == MessageBoxResult .Yes))
{
return svc.Search(myParams);
}
});
}
我收到编译错误:
Since 'System.Action<System.Threading.Tasks.Task>' returns void, a return keyword must not be followed by an object expression
所以,我的问题是,是否有可能以这种方式运行同步方法,如果是这样,我做错了什么?我的目标是可以这样调用该方法:
var data = await LoadData(params);
答案 0 :(得分:6)
添加服务引用时,可以选择生成操作的异步版本。
这是(较旧的)APM模式(IAsyncResult,BeginMethod,EndMethod)。您可以使用FromAsync:
将其挂钩到异步/等待 var task = Task.Factory.FromAsync(BeginGetResultCount, EndGetResultCount, myParams);
如果你有很多电话,那就更好了,它不会浪费那么多线程来等待I / O.
答案 1 :(得分:1)
在您的问题中,您首先声明您的客户端是在.NET 3.5上,然后继续使用async
方法并标记您的问题.NET 4.5。所以我假设你实际上是在.NET 4.5上运行。
在这种情况下,您可以告诉svcutil创建基于任务的异步API(在VS2012中,它应该默认执行此操作),然后像这样调用它们:
private async Task<ObservableCollection<MyEntity>> LoadData(ParamData param)
{
ServiceClient svc = new ServiceClient();
// Set-up parameters
myParams = BuildParams(param);
// Call a count function to see how much data we're talking about
// This call should be relatively quick
var results = await svc.GetResultCountAsync(myParams);
if (results <= 10000 ||
(MessageBox.Show("More than 10000 results, still retrieve data?"), MessageBoxButton.YesNo) == MessageBoxResult .Yes))
return await svc.Search(myParams);
}
如果 实际上是在.NET 4.0上,那么Henk有正确的答案。在这种情况下,您可能会发现我的async
WCF blog post有帮助。
答案 2 :(得分:0)
好的 - 我已经解决了这个问题。 return语句从任务返回,而不是函数;这就是为什么抱怨。
正确的代码如下所示:
private async Task<ObservableCollection<MyEntity>> LoadData(ParamData param)
{
ServiceClient svc = new ServiceClient();
int results = 0;
// Set-up parameters
myParams = BuildParams(param);
// Call a count function to see how much data we're talking about
// This call should be relatively quick
var counter = Task.Factory.StartNew(() =>
{
results = svc.GetResultCount(myParams);
});
var returnTask = counter.ContinueWith((task) =>
{
if (results <= 10000 ||
(MessageBox.Show("More than 10000 results, still retrieve data?"), MessageBoxButton.YesNo) == MessageBoxResult .Yes))
{
return svc.Search(myParams);
}
});
return returnTask.Result;
}