在 Xamarin.Forms 和 WPF 中使用异步 WCF 服务

本文关键字:异步 WCF 服务 Xamarin Forms WPF | 更新日期: 2023-09-27 18:36:15

我有这个项目:- 在控制台应用程序中托管的 WCF 服务(基本 HttpBinding)- 为我的合同分离 PCL 库- WPF 客户端- Xamarin.Forms (便携式) - 三个移动客户端。

在 WCF 中,我有异步服务,我想在每个客户端中使用它。这是我的第一个问题:PCL 不支持客户端的 TAP(基于任务的异步模式)。在PCL中,我只能以IAsyncResult Begin/End样式执行APM(异步编程模型)。让我展示我的代码:

这是我的 WCF 服务:

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract(AsyncPattern = true)]
    IAsyncResult BeginGetSum(int a, int b, AsyncCallback callback, object state);
    string EndGetSum(IAsyncResult asyncResult);
}
public class CalculatorService : ICalculatorService
{
    private Task<string> GetSum(int a, int b)
    {
        return Task.Factory.StartNew(() => (a+ b).ToString());
    }
    public IAsyncResult BeginGetSum(int a, int b, AsyncCallback callback, object state)
    {
        var tcs = new TaskCompletionSource<string>(state);
        var task = GetSum(a, b);
        task.ContinueWith(t =>
        {
            if (t.IsFaulted)
                tcs.TrySetException(t.Exception.InnerExceptions);
            else if (t.IsCanceled)
                tcs.TrySetCanceled();
            else
                tcs.TrySetResult(t.Result);
            if (callback != null)
                callback(tcs.Task);
        });
        return tcs.Task;
    }
    public string EndGetSum(IAsyncResult asyncResult)
    {
        try
        {
            return ((Task<string>)asyncResult).Result;
        }
        catch (AggregateException ex)
        {
            throw ex.InnerException;
        }
    }
}

和主机配置:

<system.serviceModel>
  <services>
    <service name="MobileWCF.ServerHost.CalculatorService">
      <endpoint address="http://localhost:9003/CalculatorService" binding="basicHttpBinding"
        contract="MobileWCF.Contracts.ICalculatorService" />
    </service>
  </services>
</system.serviceModel>

在每个客户端(Xamarin.Froms 和 WPF)中,我都使用它,如下所示:

    private void bConnect_Click(object sender, EventArgs e)
    {
        string strAddress = "http://localhost:9003/CalculatorService";
        BasicHttpBinding httpBinding = new BasicHttpBinding();
        EndpointAddress address = new EndpointAddress(strAddress);
        ChannelFactory<ICalculatorService> channel = new ChannelFactory<ICalculatorService>(httpBinding, address);
        var game = channel.CreateChannel(address);
        var num = game.BeginGetSum(4, 1, Callback, game);
    }
    private void Callback(IAsyncResult result)
    {
        var res = result.AsyncState as ICalculatorService;
        if (res != null)
            Debug.Write(res.EndGetSum(result));
    }

我的问题是:在像WPF或WinForms这样的客户端上,我想像这样使用它: await service.GetSum(1, 2); async await风格。

我的

问题是:我应该如何实现我的 WCF 协定和服务实现,以便能够在 Xamarin.Forms 客户端中的开始/结束 APM 样式中使用它,并在 WPF 或 WinForms 程序中以异步等待 TAP 样式使用它?

在 Xamarin.Forms 和 WPF 中使用异步 WCF 服务

如果您仍在寻找答案,实际上很容易。如果您查看Task.Factory您将看到一个名为 FromAsync<>() 的帮助程序方法,它完全可以执行您想要的操作。Xamarin 窗体中的客户端代码如下所示:

private async void bConnect_Click(object sender, EventArgs e)
{
    string strAddress = "http://localhost:9003/CalculatorService";
    BasicHttpBinding httpBinding = new BasicHttpBinding();
    EndpointAddress address = new EndpointAddress(strAddress);
    ChannelFactory<ICalculatorService> channel = new ChannelFactory<ICalculatorService>(httpBinding, address);
    var game = channel.CreateChannel(address);
    string num = 
        await Task.Factory.FromAsync<int, int, string> (
            game.BeginGetSum,
            game.EndGetSum,
            4, 1,
            null);
    Debug.Write(num);
}

请注意,我将 Click 处理程序的签名更改为 async void 以启用异步/等待语法。

主要要点是,FromAsync<>()为您提供了一种将一对 APM 开始/结束方法签名包装到可等待的 TPL Task 对象中的简单方法。

请试一试。如果你已经继续前进了(这个问题现在已经有一周了),那么至少把它放在你的脑海中,以备下次使用。