如何使用 WCF 修复 WPF 中损坏的服务和 return 数据?

How to fix broken Service and return data in WPF with WCF?

我有一个 WPF 应用程序,我想在其中 return 数据列表或用户调用它时的任何数据。我还需要调用 WCF 服务来获取数据。如果服务因任何原因停机,我想修复损坏的服务或等待服务处于活动状态并 return 数据怎么办?让我告诉你我在做什么:

    public List<MyData> GetMyData()
    {
           try
           {
               var  data =GetOrCreateChannel().GetMyData(); //GetOrCreateChannel method create WCF service channel
              return data;
           }
           catch(Exception ex)
           {
               _log.error(ex);
                FixedBrokenService()
                return GetMyData(); //Call again this method.
           }
    }

在上面的方法中,如果服务不是运行,它将转到catch块并再次调用相同的方法,直到除非服务关闭。每当服务启动时,它都会 return 数据。我想知道这种方法好不好?如果服务中断 2 到 3 小时,它会递归调用方法,并且内存中的堆栈大小会增加。还有其他方法吗?

尝试使用带有 ClientBase 的 wcf 客户端(有大量示例)。您可以注册一个名为 InnerChannel.Faulted 的 InnerChannel 事件。当该事件被调用时,这意味着服务以某种方式失败了。

相反,如果在 catch 中立即重试连接,您可以编写一个单独的线程,在服务中断时重试与客户端的连接。

What if service is down for 2 to 3 hour it wil recursivly call method and the stack size in memory will increasing. Is there any other approach?

我想你问这个问题是因为你已经感觉到可能有其他方法可以改进你目前所拥有的东西;我猜你正在寻找一些标准。

如果是这样,我会推荐 Google 的 指数退避 指南,here 应用于 Google 地图调用。

想法是在对 Web 服务的后续调用之间引入 延迟增加以防重复失败。

一个简单的更改是:

public List<MyData> GetMyData()
{
    List<MyData> data = null;
    int delayMilliseconds = 100;
    bool waitingForResults = true;

    while (waitingForResults)
    {
        try
        {
            data = GetOrCreateChannel().GetMyData();

            waitingForResults = false; // if this executes, you've got your data and can exit
        }
        catch (Exception ex)
        {
            _log.error(ex);
            FixedBrokenService();

            Thread.Sleep(delayMilliseconds); // wait before retrying
            delayMilliseconds = delayMilliseconds * 2; // increase your delay
        }
    }
    return data;
}

这样你也不必处理递归;不要忘记添加 using System.Threading;到顶部。


既然你提到了 WPF,我们可能想采纳 Jeroen 的建议并在另一个线程中等待:这意味着你的 WPFGUI 不会被冻结您尝试重新连接,但它会被启用,并且可能会显示微调器、等待消息或类似的东西(例如 "Reconnecting in x seconds")。

这需要更改倒数第二行,即 Thread.Sleep(delayMilliseconds);Wait(delayMilliseconds); 并在下面添加这两个方法 GetMyData:

private async static Task Wait(int delayMilliseconds)
{
    await WaitAsync(delayMilliseconds);
}

private static Task WaitAsync(int delayMilliseconds)
{
    Thread.Sleep(delayMilliseconds);
    return new Task(() => { });
}