我不认为这是一个“我想做一个同步调用”的问题。您真正要做的就是在完成后将一系列异步调用捆绑在一起。
我之前遇到过这种情况,您有一个项目列表并且需要从服务器异步获取它们的属性(例如一些状态),但还想更新屏幕上的一些加载进度指示器。
在这种情况下,您不希望在更新所有项目时阻塞 UI 线程(如果有替代方案,阻塞线程无论如何都是邪恶的)。
所以我使用了这样的控件类:
public class GroupAction
{
public delegate void ActionCompletion();
private uint _count = 0;
private ActionCompletion _callback;
private object _lockObject = new object();
public GroupAction(uint count, ActionCompletion callback)
{
_count = count;
_callback = callback;
}
public void SingleActionComplete()
{
lock(_lockObject)
{
if (_count > 0)
{
_count--;
if (_count == 0) _callback();
}
}
}
}
您使用计数(用于项目数)和在所有项目完成时执行的回调创建此操作。基本上就像一个信号量,有更多的控制,不用担心线程。
调用代码看起来像这样(我的示例基于调用您可以在 w3schools.com 找到的标准临时转换 Web 服务)。
private void DoGroupCall()
{
uint count = 5;
GroupAction action = new GroupAction(count,
() =>
{
MessageBox.Show("Finished All Tasks");
});
for (uint i = 0; i < count; i++)
{
TempConvertHttpPost proxy = new TempConvertHttpPostClient(new BasicHttpBinding(), new EndpointAddress("http://localhost/webservices/tempconvert.asmx"));
CelsiusToFahrenheitRequest request = new CelsiusToFahrenheitRequest() { Celsius = "100" };
proxy.BeginCelsiusToFahrenheit(request,
(ar) => Deployment.Current.Dispatcher.BeginInvoke(
() =>
{
CelsiusToFahrenheitResponse response = proxy.EndCelsiusToFahrenheit(ar);
// Other code presumably...
action.SingleActionComplete();
}
), null);
}
}
注意如何使用内联回调委托定义 GroupAction 实例,然后每次服务返回时调用 SingleCallBack 函数。
希望这会有所帮助...