C# 捕捉';System.ServiceModel.EndpointNotFoundException';异步web服务调用期间发生异常

C# 捕捉';System.ServiceModel.EndpointNotFoundException';异步web服务调用期间发生异常,c#,web-services,wcf,soap,exception-handling,C#,Web Services,Wcf,Soap,Exception Handling,我正在创建一个使用C#中的SOAP web服务的应用程序。我使用svcutil工具为web服务WSDL生成了一个代理类 我将代理类添加到代码中,并使用它来调用web服务并异步获取结果 当客户端可以访问互联网时,一切都很正常。但是,如果在应用程序没有Internet访问权限的情况下运行“尝试访问”,则会导致崩溃,引发以下异常: An exception of type 'System.ServiceModel.EndpointNotFoundException' occurred in Syste

我正在创建一个使用C#中的SOAP web服务的应用程序。我使用
svcutil
工具为web服务WSDL生成了一个代理类

我将代理类添加到代码中,并使用它来调用web服务并异步获取结果

当客户端可以访问互联网时,一切都很正常。但是,如果在应用程序没有Internet访问权限的情况下运行“尝试访问”,则会导致崩溃,引发以下异常:

An exception of type 'System.ServiceModel.EndpointNotFoundException' occurred in
System.ServiceModel.Internals.dll but was not handled in user code
我试图捕获此异常以防止应用程序崩溃并向用户提供更友好的错误消息,但是,由于我正在执行异步web调用,仅通过
try
-
catch
围绕web服务调用是没有帮助的

根据异常详细信息,它发生在自动生成的代理文件中定义的
End\u FunctionName
函数中


关于如何优雅地处理此异常,有什么建议吗?

很难确切知道发生了什么;然而,我将假设您有这样一个web服务

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    String Hello(String Name);

    [OperationContract]
    Person GetPerson();
}
您可能有这样一个代理:

public class MyPipeClient : IMyService, IDisposable
{
    ChannelFactory<IMyService> myServiceFactory;

    public MyPipeClient()
    {
        //This is likely where your culprit will be.
        myServiceFactory = new ChannelFactory<IMyService>(new NetNamedPipeBinding(), new EndpointAddress(Constants.myPipeService + @"/" + Constants.myPipeServiceName));
    }

    public String Hello(String Name)
    {
        //But this is where you will get the exception
        return myServiceFactory.CreateChannel().Hello(Name);
    }

    public Person GetPerson()
    {
        return myServiceFactory.CreateChannel().GetPerson();
    }

    public void Dispose()
    {
        ((IDisposable)myServiceFactory).Dispose();
    }
}
公共类MyPipeClient:IMyService,IDisposable
{
渠道工厂-我的服务工厂;
公共MyPipeClient()
{
//这很可能是你的罪魁祸首所在。
myServiceFactory=new ChannelFactory(new NetNamedPipeBinding(),new EndpointAddress(Constants.myPipeService+/“+Constants.myPipeServiceName));
}
公共字符串Hello(字符串名称)
{
//但这就是你会得到例外的地方
返回myServiceFactory.CreateChannel().Hello(名称);
}
公众人物
{
返回myServiceFactory.CreateChannel().GetPerson();
}
公共空间处置()
{
((IDisposable)myServiceFactory).Dispose();
}
}
如果连接时出错,则不会在尝试连接到通道工厂时收到错误,而是在实际尝试调用函数时收到错误

要解决此问题,可以在每个函数调用周围放置一个try-catch,并手动处理异步调用

相反,您可以有一个类似init()的函数,每次实例化连接时都会同步调用该函数。这样你就知道,如果那个电话接通了,你就接通了

如果您随时面临连接中断的风险,我建议您使用前一种选择

无论如何,下面是一个如何修复的示例:

public class MyPipeClient : IMyService, IDisposable
{
    ChannelFactory<IMyService> myServiceFactory;

    public MyPipeClient()
    {
        myServiceFactory = new ChannelFactory<IMyService>(new NetNamedPipeBinding(), new EndpointAddress(Constants.myPipeService + @"/" + Constants.myPipeServiceName + 2) );
    }

    public String Hello(String Name)
    {
        try 
        {
            return Channel.Hello(Name);
        }
        catch
        {
            return String.Empty;
        }
    }

    public Person GetPerson()
    {
        try 
        { 
            return Channel.GetPerson();
        }
        catch
        {
            return null;
        }
    }

    public Task<Person> GetPersonAsync()
    {
        return new Task<Person>(()=> GetPerson());
    }

    public Task<String> HelloAsync(String Name)
    {
        return new Task<String>(()=> Hello(Name));

    }

    public void Dispose()
    {
        myServiceFactory.Close();
    }

    public IMyService Channel
    {
        get
        {
            return myServiceFactory.CreateChannel();
        }
    }
}
公共类MyPipeClient:IMyService,IDisposable
{
渠道工厂-我的服务工厂;
公共MyPipeClient()
{
myServiceFactory=new ChannelFactory(new NetNamedPipeBinding(),new EndpointAddress(Constants.myPipeService+/“+Constants.myPipeServiceName+2));
}
公共字符串Hello(字符串名称)
{
尝试
{
返回频道。你好(姓名);
}
接住
{
返回字符串。空;
}
}
公众人物
{
尝试
{ 
返回Channel.GetPerson();
}
接住
{
返回null;
}
}
公共任务GetPersonAsync()
{
返回新任务(()=>GetPerson());
}
公共任务HelloAsync(字符串名称)
{
返回新任务(()=>Hello(Name));
}
公共空间处置()
{
myServiceFactory.Close();
}
公共信息服务频道
{
收到
{
返回myServiceFactory.CreateChannel();
}
}
}
我上传了我写的源代码,这样你就可以下载完整的源代码了。你可以在这里找到它:

PS:此存储库会抛出您正在获得的异常。要删除它,只需转到MyPipeClient并删除构造函数中的+2

如果使用双工,请考虑使用这个存储库:


确保您调用的异步方法正在返回Task或Task,而不是void,否则您将无法在try-catch中捕获异常。