0

Regarding my previous post: 910220 - service methods run dependently since the code and what I meant about the problem I had with it was a bit complex, I come again with a completely changed code which explains itself better.

In client side, we have:

#define USE_ONLY_ONE_INSTANCE

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using CountTester.ServiceReference1;

namespace CountTester
{
    public partial class MainPage : UserControl
    {
#if USE_ONLY_ONE_INSTANCE
        private readonly Service1Client _sc = new Service1Client();
#endif

        public MainPage()
        {
            InitializeComponent();
#if USE_ONLY_ONE_INSTANCE
            _sc.CountCompleted += OnCountCompleted;
#endif
        }

        void OnCountCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
                throw new Exception(string.Format("Count Error {0}", e.Error));
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
#if USE_ONLY_ONE_INSTANCE
                _sc.CountAsync(i);
#else
                var sc = new Service1Client();
                sc.CountCompleted += OnCountCompleted;
                sc.CountAsync(i);
                //sc.CloseAsync();
#endif
            }
        }
    }
}

this is code behind of the XAML. In the code I call a service method 100 times. I tried both cases and get exception in both cases: case 1: I use only one instance of the proxy for all communications with server. case 2: I use an instance for each communication with server.

Let's see the code at server before more description:

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Text;
using System.Threading;

namespace CountTester.Web
{
    [ServiceContract(Namespace = "")]
    [SilverlightFaultBehavior]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1
    {
        const string logFileName = @"h:\CountTester.log";
        object _logLock = new object();

        void log(string s)
        {
            lock (_logLock)
            {
                var streamWriter = new StreamWriter(logFileName, true, Encoding.ASCII);
                streamWriter.Write(s);
                streamWriter.Close();
            }
        }

        Service1()
        {
            //File.Delete(logFileName);
        }

        [OperationContract]
        public void Count(int counter)
        {
            log(string.Format("{0}\n", counter));
            Thread.Sleep(3000);
        }
    }
}

Count is the service method which is called. I deliberately wait 3 seconds in the method. what I expect is that the for at the client get accomplished with no delay. I expect the method gets called asynchronously and this means that first call doesn't affect on the second call.

In another words, if i call the method and it waits to get accomplished, calling it again doesn't get delayed.

While this is the case. how can I figure out that this happens? by using Tail for Windows, I find that the number which is logged is delayed in getting logged. I also figure out this when I see that I get time out exception in response to calling the service method (Count Error...). I hope I could clarify my question.

I also wonder when I see malfunctioning of the program (Exception), when I uncomment the line in which I've closed the service?

Please answer these two questions.

prolink007
  • 33,872
  • 24
  • 117
  • 185
hamidi
  • 117
  • 1
  • 8

1 Answers1

0

Question 1:

By default your IIS web service will only allow 2 simultaneous requests from the same IP address. This limitation is a default to stop DOS (Denial Of Service) attacks.

That means the subsequent 98 calls are waiting at least 3 seconds, per pair, while the previous ones complete. Eventually you will hit the default 30 second(?) server timeout long before the last requests are processed.

If you insist on running that many simultaneous requests (you shouldn't anyway), you will need to increase the default limits in your web.config file on the server. See my other answer here for more details

Question 2:

You should not close an async call immediately after starting it... the call is still in progress. That code makes no sense.

Notes:

Logging is delayed anyway, for efficiency, so don't use that as a guide.

Community
  • 1
  • 1
iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • thank u. so the barrier is IIS! but why this limitation must exist? indeed, my problem is that by every change in size of user control i've to inform server that the client size is changed. so if user tries not to release the mouse left button while resizing for a long time and repeatedly and continually move the cursor while hitting the mouse left button, a bunch of resize requests are sent to the server. if i use a timer to eliminate resizes occur in a short period of time, the timeout must always exist even for when it's not needed like when maximizing. – hamidi May 10 '12 at 13:00
  • 1
    The limitation is a default to stop DOS (Denial Of Service) attacks. You should not design a client app to continuously send events like that. It is normal to do most of the UI work client side and send the end results only (like final position). The `Client <=> Server` speed is not good enough for interactive updates and it will not scale up to multiple users very well at all. – iCollect.it Ltd May 10 '12 at 13:44
  • [here](http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/5546f5c2-55b4-4110-9c5e-4a234660e8b1) is told that we can close service even if it's not accomplished yet. – hamidi May 10 '12 at 13:58
  • that was really my idea to determine the last size change and wait until then and send the last size change to the server, but it cannot be detected when the size change has been ended and the user has released the mouse left button. – hamidi May 10 '12 at 14:00
  • 1
    @hamidi: "You should close your proxy *when you don't expect further communication with the service*. This includes making sure you got all the response for the requests you made" – iCollect.it Ltd May 10 '12 at 15:02
  • @hamidi: Use a timer to send the last recorded value (basically reset the timer whenever you have activity). – iCollect.it Ltd May 10 '12 at 15:03
  • oh ic. so i may close service when its ...Complete got called? – hamidi May 12 '12 at 06:04
  • using a timer is a good idea, but in case the user doesn't need to wait, like when he maximizes the window, he has to wait for the timeout i specify. – hamidi May 12 '12 at 06:05