我们正在实现一个需要通过https使用外部API的MVC2站点(我们不能使用WCF甚至是老式的SOAP Web服务,我担心)。我们在需要与API通信的地方使用AsyncController
,到目前为止一切正常。
我们需要一些场景,我们需要串联多个API调用,使用一步的结果来执行下一个。
到目前为止,一般模式(为演示目的而简化)如下:
public class WhateverController : AsyncController
{
public void DoStuffAsync(DoStuffModel data)
{
AsyncManager.OutstandingOperations.Increment();
var apiUri = API.getCorrectServiceUri();
var req = new WebClient();
req.DownloadStringCompleted += (sender, e) =>
{
AsyncManager.Parameters["result"] = e.Result;
AsyncManager.OutstandingOperations.Decrement();
};
req.DownloadStringAsync(apiUri);
}
public ActionResult DoStuffCompleted(string result)
{
return View(result);
}
}
我们有几个需要并行执行API调用的操作已经很好了;我们只是执行多个请求,并确保正确地增加AsyncManager.OutstandingOperations
。
要串行执行多个API服务请求,我们目前正在为第一个请求的DownloadStringCompleted
调用事件处理程序中的下一步。例如,
req.DownloadStringCompleted += (sender, e) =>
{
AsyncManager.Parameters["step1"] = e.Result;
OtherActionAsync(e.Result);
AsyncManager.OutstandingOperations.Decrement();
}
其中OtherActionAsync
是在同一个控制器中定义的另一个动作,遵循上面定义的相同模式。
在访问AsyncManager
中的值时,是否可以从事件处理程序中调用其他异步操作导致可能的竞争?
我试着查看MSDN,但关于AsyncManager.Sync()
的所有评论都与IAsyncCallback
的BeginMethod / EndMethod模式有关。在那种情况下,文档会警告潜在的竞争条件。
我们不需要在控制器内实际调用另一个动作,如果这对你不利。构建另一个WebClient
并在其上调用.DownloadStringAsync()
的代码可以很容易地放在第一个请求的事件处理程序中。我刚刚在这里展示了它,使其更容易阅读。
希望这是有道理的!如果没有,请发表评论,我会尝试澄清你喜欢的任何内容。
谢谢!
答案 0 :(得分:0)
事实证明答案是“不”。
(以供将来参考,任何人都可以通过搜索遇到这个问题)