我已经知道通过Silverlight调用WCF服务是异步的。我也知道很多人试图找到方法让他们出于各种愚蠢的原因(例如阻止UI线程)同步调用,并且这样的事情应该像瘟疫一样。
我只是希望能够自己处理所有线程内容,因为我发现必须挂钩/取消所有'*已完成'事件是一项额外的工作,并且是一个巨大的痛苦,特别是当你不知道电话的顺序等。有人知道一个聪明的方法来进行同步通话并自己做线程吗?
答案 0 :(得分:3)
鉴于你不应该进行同步网络呼叫,你不应该进行同步网络呼叫,你不应该进行同步网络呼叫,如果你真的,真的知道你在做什么,那么你实际上可以做同步(阻止)仅在您不在UI线程中时调用。。只是意识到它不是官方支持的场景(所以它没有像其他功能那样经过测试),但我已经尝试了几次而且它只是有效。
您需要做的就是使用[ServiceContract]
接口(而不是客户端类) - 公开Begin / End操作的接口 - 并调用EndXXX(BeginXXX(parameters, null, null))
,如下例所示(这是一个包含两个控件的页面,Button
Click
事件绑定到Button_Click
处理程序,TextBox
名为“txtDebug”,代码写入结果。
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.AddToDebug("In Button_Click");
ThreadPool.QueueUserWorkItem(delegate
{
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
ServiceReference1.Service1 asInterface = client;
this.AddToDebug("Calling server \"synchronously\"...");
int result = asInterface.EndAdd(asInterface.BeginAdd(45, 67, null, null));
this.AddToDebug("Result: {0}", result);
client.CloseAsync();
});
}
private void AddToDebug(string text, params object[] args)
{
if (args != null && args.Length > 0)
{
text = string.Format(text, args);
}
text = string.Format("[{0} - {1}] {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("HH:mm:ss.fff"), text);
this.Dispatcher.BeginInvoke(() => this.txtDebug.Text = this.txtDebug.Text + text + Environment.NewLine);
}
}
现在,如果你想从UI线程做到这一点,那么实际上,没有办法阻止并等待响应(因为响应应该也在UI线程上返回)。如果你对Begin / End模式很有帮助,你仍然可以进行异步调用,但不必担心事件处理程序被泄露。
答案 1 :(得分:1)
最好避免依赖于阻塞线程(任何线程而不仅仅是UI线程)的解决方案。线程是昂贵的资源,ThreadPool线程是有限的资源。这就是网络API首先具有回调语义的原因。
我同意Carlos的第一件事就是切换到服务提供的.NET异步模式接口而不是基于可怕事件的接口。 (基于事件的方法旨在使“开发人员思考”的UI开发人员的工作变得简单)。如果您的服务名为“Service1”,则您的客户端类将被称为“Service1Client”。但是,该类还将支持名为“Service1”的接口,该接口将具有OperationContracts的Begin / End版本。
“进行同步通话的一种聪明方式”
不阻止线程这是不可能的。然而,使一系列任务同步并不是真正的要求。我们想要的只是确保在序列中发生一系列任务。您可以通过从上一个任务的回调方法调用下一个任务来完成此操作,但嵌套会成为一个问题。
看看这个articles系列可能从.NET Asynchronous Pattern开始。不幸的是,一篇WCF文章仍在进行中,但我确实很快就会发布,这些东西经常出现在这里。
答案 2 :(得分:-1)
如果将调用包装在另一个函数中,该函数将在异步调用返回之前休眠,该怎么办?