简单场景:
考虑到这一点,我有两件事需要解决(但我不知道如何):
1 - 使GetSiteInfo()成为异步调用;
2 - 仅在返回来自GetSiteInfo()的所有异步调用后将GetAboutInfo()返回给客户端;
注意:由于我们仍然使用.Net 3.5,因此无法使用“任务”。 目前我正在研究IAsyncResult(使用Begin / End方法),但找不到任何可以让我适应下面的当前代码的内容。 (我在循环中从中央WCF调用远程服务器。)
请记住,除了仅存在于“CENTRAL WCF服务器”(调用远程服务器的WCF)中的循环之外,下面的WCF在所有远程服务器中都是相同的。这是部分WCF代码:
[ServiceContract]
public interface IAbout
{
[OperationContract(Name = "About_GetAboutInfo")]
[WebGet(UriTemplate = "/GetAboutInfo", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
About.AboutInfo GetAboutInfo();
[OperationContract(Name = "About_GetSiteInfo")]
[WebGet(UriTemplate = "/GetSiteInfo", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
About.SiteInfo GetSiteInfo();
}
public SiteInfo GetSiteInfo()
{
SiteInfo siteInfo = new SiteInfo();
//...code stripped out...
return (siteInfo);
}
public AboutInfo GetAboutInfo()
{
AboutInfo aboutInfo = new AboutInfo();
SiteInfo siteInfo = new SiteInfo()
{
ID = site.ID
,Name = site.Name
,DatabaseVersion = "Unavailable"
};
foreach (Site site in sites)
{
try
{
string uri = Utilities.CombineUri(site.Uri, "svc/About.svc/ws");
AboutServiceClient wcfClient = new AboutServiceClient("About");
wcfClient.Endpoint.Address = new EndpointAddress(uri);
SiteInfo childSiteInfo = wcfClient.GetSiteInfo(); <== call is blocked here until I get a response from remote server
siteInfo.DatabaseVersion = childSiteInfo.DatabaseVersion;
}
catch (Exception e)
{ //...code stripped out... }
aboutInfo.Sites.Add(siteInfo); <== this should only be returned after we receive response from all calls
}
...
public class AboutServiceClient : ClientBase<IAbout>
{
public AboutServiceClient(Binding Binding, EndpointAddress Address) : base(Binding, Address)
{
if (Binding is WebHttpBinding)
{
this.Endpoint.Behaviors.Add(new WebHttpBehavior());
}
}
public AboutServiceClient(string endpointConfigurationName) : base(endpointConfigurationName)
{ }
public About.SiteInfo GetSiteInfo()
{ return base.Channel.GetSiteInfo(); }
public About.AboutInfo GetAboutInfo()
{ return base.Channel.GetAboutInfo(); }
}
谢谢
答案 0 :(得分:1)
使用.NET 3.5是一个主要的限制。您将无法保持线性代码流。这是新的工作流程:
BeginGetAboutInfo
/ EndGetAboutInfo
。 BeginGetAboutInfo
中,您将使用wcfClient.GetSiteInfoBegin
(并行)向远程WCF服务启动80个异步请求,并跟踪每个IAsyncResult
。 wcfClient.EndSiteInfoBegin
来检索并存储每个操作的结果。BeginGetAboutInfo
时提供的回调。EndGetAboutInfo
,在那里您可以提供所有80项操作的综合结果。答案 1 :(得分:0)
您可以从NuGEt安装“.NET 3.5任务并行库”并以此方式使用任务。然后,您可以使用Task.Factory.FromAsync包裹wcfClient.GetSiteInfoBegin
和wcfClient.EndSiteInfoBegin
方法。
这是未经测试的,但也许是这样的:
public AboutInfo GetAboutInfo()
{
AboutInfo aboutInfo = new AboutInfo();
SiteInfo siteInfo = new SiteInfo()
{
ID = site.ID
,Name = site.Name
,DatabaseVersion = "Unavailable"
};
var tasks = new List<Task<SiteInfo>>();
foreach (Site site in sites)
{
try
{
string uri = Utilities.CombineUri(site.Uri, "svc/About.svc/ws");
AboutServiceClient wcfClient = new AboutServiceClient("About");
wcfClient.Endpoint.Address = new EndpointAddress(uri);
tasks.Add(Task<SiteInfo>.Factory.FromAsync(wcfClient.GetSiteInfoBegin, wcfClient.EndSiteInfoBegin, null)
.ContinueWith(t =>
{
siteInfo.DatabaseVersion = t.Result.DatabaseVersion.DatabaseVersion;
}, TaskScheduler.FromCurrentSynchronizationContext()));
}
catch (Exception e)
{ //...code stripped out...
}
}
Task.WhenAll(tasks.ToArray()).ContinueWith
( ts =>
{
ts.ForEach( t => aboutInfo.Sites.Add(t.Rrsult);
});
return aboutInfo;
}