Silverlight和同步调用WCF

时间:2011-09-29 19:10:08

标签: c# silverlight wcf

我已经知道通过Silverlight调用WCF服务是异步的。我也知道很多人试图找到方法让他们出于各种愚蠢的原因(例如阻止UI线程)同步调用,并且这样的事情应该像瘟疫一样

我只是希望能够自己处理所有线程内容,因为我发现必须挂钩/取消所有'*已完成'事件是一项额外的工作,并且是一个巨大的痛苦,特别是当你不知道电话的顺序等。有人知道一个聪明的方法来进行同步通话并自己做线程吗?

3 个答案:

答案 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)

如果将调用包装在另一个函数中,该函数将在异步调用返回之前休眠,该怎么办?