Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 由于关闭本地通道,HTTP请求中止WCF错误_C#_.net_Wcf_.net 4.5_Channelfactory - Fatal编程技术网

C# 由于关闭本地通道,HTTP请求中止WCF错误

C# 由于关闭本地通道,HTTP请求中止WCF错误,c#,.net,wcf,.net-4.5,channelfactory,C#,.net,Wcf,.net 4.5,Channelfactory,我有一个简单的WCF服务 using System.Runtime.Serialization; using System.ServiceModel; using System.Threading.Tasks; namespace Interface { [ServiceContract] public interface IService1 { [OperationContract] Task<A> DoWorkAsync

我有一个简单的WCF服务

using System.Runtime.Serialization;
using System.ServiceModel;
using System.Threading.Tasks;

namespace Interface
{

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        Task<A> DoWorkAsync(A a);
    }


    [DataContract]
    public class A
    {
        [DataMember]
        public int B { get; set; }
    }
}
以及一个单元测试(使用NUnit),它向服务发送一些请求:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Interface;
using NUnit.Framework;

namespace WcfTests
{
    [TestFixture]
    public class Test
    {
        public const int NumberOfCalls = 100;

        [Test]
        public void UseService()
        {
            var baseAddresses = new Uri("http://localhost:8080/service1");

            var binding = new BasicHttpBinding
                          {
                              SendTimeout = TimeSpan.FromMilliseconds(900)
                          };


            var endpoint = new EndpointAddress(baseAddresses);

            using (var factory = new ChannelFactory<IService1>(binding, endpoint))
            {
                IService1 client = factory.CreateChannel();

                var r = new Random();

                try
                {
                    var seed = Enumerable.Range(0, NumberOfCalls)
                        .Select(i => r.Next(6, 100)).ToList();

                    Console.WriteLine("Expected to fail: {0}", seed.Count(t => t <= 5));

                    var tasks = seed.Select(rnd => MakeACall(client, rnd)).ToArray();

                    Task.WaitAll(tasks);

                    Console.WriteLine("failed = {0}", tasks.Count(t => !t.Result));
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
                finally
                {
                    Console.WriteLine("Program.UseService.finally");
                    var c = client as IClientChannel;
                    if (c != null)
                    {
                        c.Close();
                    }
                }
            }

            Console.WriteLine("{0} unique exceptions", UniqueExceptions.Count);
            foreach (var uniqueException in UniqueExceptions)
            {
                Console.WriteLine(uniqueException.Value);
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();
            }
        }

        public ConcurrentDictionary<string, string> UniqueExceptions = new ConcurrentDictionary<string, string>();

        public async Task<bool> MakeACall(IService1 client, int rnd)
        {
            bool result = true;

            var a = new A
            {
                B = rnd
            };

            try
            {
                await client.DoWorkAsync(a);
            }
            catch (Exception e)
            {
                var exInfo = e.ToString();

                var hasher = SHA256.Create();
                var hash = Encoding.UTF8.GetString(hasher.ComputeHash(Encoding.UTF8.GetBytes(exInfo)));

                UniqueExceptions.TryAdd(hash, exInfo);

                result = false;
            }

            return result;
        }
    }
}
使用系统;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用System.Linq;
使用System.Security.Cryptography;
使用System.ServiceModel;
使用系统文本;
使用系统线程;
使用System.Threading.Tasks;
使用接口;
使用NUnit.Framework;
命名空间WcfTests
{
[测试夹具]
公开课考试
{
public const int NumberOfCalls=100;
[测试]
公共服务
{
var baseAddresses=新Uri(“http://localhost:8080/service1");
var binding=新的BasicHttpBinding
{
SendTimeout=TimeSpan.From毫秒(900)
};
var端点=新端点地址(基本地址);
使用(var factory=newchannelfactory(绑定,端点))
{
IService1 client=factory.CreateChannel();
var r=新的随机变量();
尝试
{
var seed=可枚举的范围(0,NumberOfCalls)
.Select(i=>r.Next(6100)).ToList();
WriteLine(“预期失败:{0}”,seed.Count(t=>t MakeACall(client,rnd)).ToArray();
Task.WaitAll(任务);
WriteLine(“failed={0}”,tasks.Count(t=>!t.Result));
}
捕获(例外e)
{
Console.WriteLine(如ToString());
}
最后
{
WriteLine(“Program.UseService.finally”);
var c=作为IClientChannel的客户端;
如果(c!=null)
{
c、 Close();
}
}
}
WriteLine(“{0}唯一异常”,UniqueExceptions.Count);
foreach(UniqueExceptions中的var uniqueException)
{
Console.WriteLine(uniqueException.Value);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
Console.WriteLine();
}
}
public ConcurrentDictionary UniqueExceptions=新建ConcurrentDictionary();
公共异步任务MakeACall(IService1客户端,int rnd)
{
布尔结果=真;
var a=新a
{
B=rnd
};
尝试
{
等待client.doworksync(a);
}
捕获(例外e)
{
var exInfo=e.ToString();
var hasher=SHA256.Create();
var hash=Encoding.UTF8.GetString(hasher.ComputeHash(Encoding.UTF8.GetBytes(exInfo));
TryAdd(散列,exInfo);
结果=假;
}
返回结果;
}
}
}
问题是:当我运行测试时,我得到3个错误(我希望没有错误):

  • 两个超时:一个是00:00:00.9000000,另一个是不同的时间,但看起来像是00:00:00.6460000
  • 还有一个异常,比如HTTP请求http://localhost:8080/service1'已中止。这可能是由于本地通道在请求仍在进行时被关闭。如果不需要此行为,请更新代码,使其在请求操作仍在进行时不会关闭通道。-->System。Net.WebException:请求被中止:请求被取消。
  • 为什么会发生这些异常,尤其是第二个异常


    更新:

    似乎将超时设置为900ms是个坏主意,从1300ms超时和1400ms延迟开始,2d错误消失了。这很奇怪,我仍然想知道为什么会发生这种情况

    第一个错误是由于WCF“预热”(或者可能是因为我的实现很糟糕)-如果您得到一个更大的数字,比如400个请求-第一次运行测试时失败约290个请求,第二次(如果您真的很快)失败约140个请求,3d时间-~30个请求,之后如果您运行测试非常快,则不会出现错误


    另外,如果你很好奇-尝试大量的请求,比如3000个,你也会在那里得到一个有趣的错误。

    我想我不明白你为什么要强制执行这么低的超时阈值?我相信默认的SendTimeout是60秒,大大高于你的900ms-1400ms范围。这个示例主要是教育性的,我是r在WCF和900毫秒范围内搜索async/await只是一种使测试快速失败的方法。但是,对一个响应请求的服务进行web调用需要很多时间……因此我认为WCF没有理由进行故障转移
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                var baseAddresses = new Uri("http://localhost:8080/service1");
    
                using (var host = new ServiceHost(typeof (Service1), baseAddresses))
                {
                    var serviceMetadataBehavior = new ServiceMetadataBehavior
                                                  {
                                                      HttpGetEnabled = true,
                                                      MetadataExporter =
                                                      {
                                                          PolicyVersion = PolicyVersion.Policy15
                                                      }
                                                  };
                    host.Description.Behaviors.Add(serviceMetadataBehavior);
    
                    host.Open();
    
                    Console.WriteLine("Running, press Enter to exit");
                    Console.ReadLine();
    
                    host.Close();
                }
            }
        }
    }
    
    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.ServiceModel;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Interface;
    using NUnit.Framework;
    
    namespace WcfTests
    {
        [TestFixture]
        public class Test
        {
            public const int NumberOfCalls = 100;
    
            [Test]
            public void UseService()
            {
                var baseAddresses = new Uri("http://localhost:8080/service1");
    
                var binding = new BasicHttpBinding
                              {
                                  SendTimeout = TimeSpan.FromMilliseconds(900)
                              };
    
    
                var endpoint = new EndpointAddress(baseAddresses);
    
                using (var factory = new ChannelFactory<IService1>(binding, endpoint))
                {
                    IService1 client = factory.CreateChannel();
    
                    var r = new Random();
    
                    try
                    {
                        var seed = Enumerable.Range(0, NumberOfCalls)
                            .Select(i => r.Next(6, 100)).ToList();
    
                        Console.WriteLine("Expected to fail: {0}", seed.Count(t => t <= 5));
    
                        var tasks = seed.Select(rnd => MakeACall(client, rnd)).ToArray();
    
                        Task.WaitAll(tasks);
    
                        Console.WriteLine("failed = {0}", tasks.Count(t => !t.Result));
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.ToString());
                    }
                    finally
                    {
                        Console.WriteLine("Program.UseService.finally");
                        var c = client as IClientChannel;
                        if (c != null)
                        {
                            c.Close();
                        }
                    }
                }
    
                Console.WriteLine("{0} unique exceptions", UniqueExceptions.Count);
                foreach (var uniqueException in UniqueExceptions)
                {
                    Console.WriteLine(uniqueException.Value);
                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine();
                }
            }
    
            public ConcurrentDictionary<string, string> UniqueExceptions = new ConcurrentDictionary<string, string>();
    
            public async Task<bool> MakeACall(IService1 client, int rnd)
            {
                bool result = true;
    
                var a = new A
                {
                    B = rnd
                };
    
                try
                {
                    await client.DoWorkAsync(a);
                }
                catch (Exception e)
                {
                    var exInfo = e.ToString();
    
                    var hasher = SHA256.Create();
                    var hash = Encoding.UTF8.GetString(hasher.ComputeHash(Encoding.UTF8.GetBytes(exInfo)));
    
                    UniqueExceptions.TryAdd(hash, exInfo);
    
                    result = false;
                }
    
                return result;
            }
        }
    }