none
也问一个WCF request timeout的问题 RRS feed

  • 问题

  • 我在service端写了一个一直产生随机数的sub,把产生出的随机数扔进一个全局变量。我在service的构造函数里创建一个线程去运行这个sub。也就是当这个service被调起来的时候,就会有一个线程一直在产生随机数。我提供一个公开的返回这个全局变量的function,然后我用client去调这个function得到service端产生的这个随机数。但是当我在client端不停调用这个function的时候,就会不定时出现request channel timed out。

    我配置<ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Single, InstanceContextMode:=InstanceContextMode.Single)>,如果只开一个client,运行较长时间才会抛出request channel timed out,如果开多个client很快就会出现timeout异常。

    貌似是线程阻塞造成的。这个要怎么解决呢?
    2009年2月25日 7:38

答案

  • 首先你这样不停产生随机的方法会吃掉你server上的所有CPU资源....
    有可能是因为这样所以你的请求得不到及时的响应

    建议你把Server Code改成这样:
    [ThreadStatic]  
    private static Random ran=new Random();  
     
    public int GetData()     
    {     
          return ran.Next(10000);  

    这样你有一个ThreadStatic的Random对象,就不会有线程安全的问题
    你也可以把ConcurrencyMode设成Multi

    这样可以显著提高你的Service的效率,同时降低系统资源开销
    2009年3月16日 13:28

全部回复

  • 楼主,您好,
    您的问题实在是无法重现,你能给个项目工程过来吗?
    我个人建议您看看这两篇博客,上面讲的很全,或许您能从上面找到点你想要的东西,

    http://www.cnblogs.com/artech/archive/2007/02/26/656901.html



    http://www.cnblogs.com/jillzhang/archive/2008/08/30/1279939.html
    Asp.net
    2009年3月3日 8:11
  • 十分感激,不知怎么把工程给您呢?我贴一下代码,另外给个链接,希望可以得到您的帮助,谢谢!

    我仅仅是在wcfservice工程的基础上做了简单修改。
    service 端的代码:
    namespace WcfService1  
    {  
        // 增加SessionMode.NotAllowed  
        [ServiceContract(SessionMode=SessionMode.NotAllowed)]  
        public interface IService1  
        {  
     
            [OperationContract]  
            int GetData();  
     
     
            // GetData改成单纯返回值,删除了数据契约相关内容  
        }  
     
        [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single, InstanceContextMode=InstanceContextMode.Single)]  
        public class Service1 : IService1  
        {  
            static int data;  
     
            public Service1() {  
                //在线程中运行赋值过程  
                System.Threading.Thread myThread = new System.Threading.Thread(new System.Threading.ThreadStart(ShareData));  
                myThread.Start();  
            }  
     
            //返回当前随机数  
            public int GetData()  
            {  
                return data;  
            }  
     
            //不停地将随机数赋值给静态变量  
            private void ShareData()  
            {  
                Random autoRand = new Random();  
                while (true) {  
                    data = RunIntRandoms(autoRand);  
                }  
            }  
     
            //产生随机数  
            private int RunIntRandoms(Random randObj){  
                return randObj.Next(10000);  
            }  
     
        }  

    client 端的代码(做5000次GetData,并打印一下每次出现timeout的时间间隔):
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel""3.0.0.0")]  
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName="IService1", SessionMode=System.ServiceModel.SessionMode.NotAllowed)]  
    public interface IService1  
    {  
          
        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetData", ReplyAction="http://tempuri.org/IService1/GetDataResponse")]  
        int GetData();  
    }  
     
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel""3.0.0.0")]  
    public interface IService1Channel : IService1, System.ServiceModel.IClientChannel  
    {  
    }  
     
    [System.Diagnostics.DebuggerStepThroughAttribute()]  
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel""3.0.0.0")]  
    public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1  
    {  
          
        public Service1Client()  
        {  
        }  
          
        public Service1Client(string endpointConfigurationName) :   
                base(endpointConfigurationName)  
        {  
        }  
          
        public Service1Client(string endpointConfigurationName, string remoteAddress) :   
                base(endpointConfigurationName, remoteAddress)  
        {  
        }  
          
        public Service1Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :   
                base(endpointConfigurationName, remoteAddress)  
        {  
        }  
          
        public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :   
                base(binding, remoteAddress)  
        {  
        }  
          
        public int GetData()  
        {  
            return base.Channel.GetData();  
        }  
    }  
     
    class client  
        {  
            static DateTime date1;  
            static void Main(string[] args)  
            {  
     
                Service1Client client = new Service1Client();  
                date1 = DateTime.Now;  
                var j = 1;  
                for (var i = 0; i < 5000; i++)  
                {  
                      
                    Console.Write("{0}:", j);  
                    DoClient(client);  
                    j++;  
                      
                }  
     
                client.Close();  
                Console.WriteLine();  
                Console.WriteLine("Press <ENTER> to terminate client.");  
                Console.ReadLine();  
            }  
     
            private static void DoClient(Service1Client client)  
            {  
                try 
                {  
                    Console.WriteLine(client.GetData());  
                }  
                catch (Exception ex)  
                {  
                    TimeSpan difference;  
     
                    difference = date1 - DateTime.Now;  
                    Console.WriteLine("{0},{1}" ,difference, ex.ToString());  
     
                    date1 = DateTime.Now;  
                }  
     
            }  
        } 


    我的service是基于iis运行的,web.config以及客户端的app.config就是默认生成的,我在iis上创建了一个叫remotedata的web application,把地址指向工程里service的目录,所以客户端的endpoint address="http://localhost/RemoteData/Service1.svc"。

    工程链接


    2009年3月5日 2:34
  • 有高手帮忙看看吗?

    谢谢
    2009年3月10日 5:56
  • 首先你这样不停产生随机的方法会吃掉你server上的所有CPU资源....
    有可能是因为这样所以你的请求得不到及时的响应

    建议你把Server Code改成这样:
    [ThreadStatic]  
    private static Random ran=new Random();  
     
    public int GetData()     
    {     
          return ran.Next(10000);  

    这样你有一个ThreadStatic的Random对象,就不会有线程安全的问题
    你也可以把ConcurrencyMode设成Multi

    这样可以显著提高你的Service的效率,同时降低系统资源开销
    2009年3月16日 13:28