async calls

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a simple windows application project. It has a form which has 2
buttons. The project has a web service reference. The web service has two web
methods Helloworld1 and Helloworld2 they both return "Hello world".
Helloworld1 has a 120 seconds delay.
One of the buttons on the form makes a async call to Helloworld1 web method
and the other button makes a sync call to Helloworld2. The problem is: if I
click on the button1 twice and try to click on the button 2. Application
hangs about 100 seconds and returns with a time out exception, in some cases
it returns the "Underlying connection is closed" exception.
Now I get the error if the web service is in a different machine then I'm
running the exe in. I tried this with both {win 2000 machine + IIS 5} and
{win 2003 server + IIS 6} with same result. If I 'm connecting to the local
web service, I don't get an error.
Is this a bug?


Here is Win app:
Imports System.Web.Services.Protocols
Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(40, 24)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Async Call"
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(40, 64)
Me.Button2.Name = "Button2"
Me.Button2.TabIndex = 1
Me.Button2.Text = "Sync Call"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(160, 126)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
AsyncTickler()
End Sub

Private wcrAsyncTicklerResult As WebClientAsyncResult
Dim objAsyncWebSvc1 As New localhost.Service1

Private Sub AsyncTickler()
Try
Application.DoEvents()
wcrAsyncTicklerResult =
objAsyncWebSvc1.BeginHelloWorld1(Nothing, Nothing)
Catch excGeneric As Exception
MessageBox.Show(excGeneric.ToString)
Finally
End Try
End Sub

Dim objSyncWebSvc1 As New localhost.Service1
Dim dtm As DateTime
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Try
dtm = Now
MessageBox.Show(objSyncWebSvc1.HelloWorld2())
Catch excGeneric As Exception
Dim lng As Long = Now.Ticks - dtm.Ticks
Dim dtm1 As New DateTime(lng)
MessageBox.Show("Response came back in " & dtm1.Minute & "mins
and " & dtm1.Second & " secs " & excGeneric.ToString)
Finally
End Try
End Sub
End Class

Here is Web Service:
Imports System.Web.Services

<System.Web.Services.WebService(Namespace :=
"http://tempuri.org/AsyncTesterWS/Service1")> _
Public Class Service1
Inherits System.Web.Services.WebService

#Region " Web Services Designer Generated Code "

Public Sub New()
MyBase.New()

'This call is required by the Web Services Designer.
InitializeComponent()

'Add your own initialization code after the InitializeComponent() call

End Sub

'Required by the Web Services Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Web Services Designer
'It can be modified using the Web Services Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
components = New System.ComponentModel.Container()
End Sub

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
'CODEGEN: This procedure is required by the Web Services Designer
'Do not modify it using the code editor.
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

#End Region

' WEB SERVICE EXAMPLE
' The HelloWorld() example service returns the string Hello World.
' To build, uncomment the following lines then save and build the project.
' To test this web service, ensure that the .asmx file is the start page
' and press F5.
'
<WebMethod()> _
Public Function HelloWorld1() As String
System.Threading.Thread.Sleep(120000)
Return "Hello World"
End Function

<WebMethod()> _
Public Function HelloWorld2() As String
Return "Hello World"
End Function

End Class
 
Hi Mach2,

Welcome to MSDN newsgroup.
Regarding on the problem you described, I think it is caused by the default
two http connection limitation of each .net application. In .net , there
are connection management configuration settings which control the
connections allowed to remote servers. The setting are under the
<system.net>
<connectionManagement>

#<connectionManagement> Element
http://msdn.microsoft.com/library/en-us/cpgenref/html/gngrfconnectionmanagem
entelement.asp?frame=true

the default connection limitation for every remote server is 2. That's why
you'll found your 3rd request to a single server pending until one of the
former 2 complete. We can override the limitation for that certain server
in our client app's app.config, for example:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<connectionManagement>
<add address = "http://remoteserver/HelloService/Service1.asmx"
maxconnection = "4" />
<add address = "*" maxconnection = "2" />
</connectionManagement>
</system.net>
</configuration>

the above app.config adjust the connection limit for "remoteserver" to 4.
Then, we can make at most 4 requests concurrently to that server.

In addition, the following kb article also include this info and some other
common issues we may meet when consuming asp.net webservice in .net client
app.

#PRB: Contention, poor performance, and deadlocks when you make Web service
requests from ASP.NET applications
http://support.microsoft.com/?id=821268

Hope also helps.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Steven,
Thanks a lot that seems to be the problem. I have increased the max
connection count and I don't have the problem anymore. But one other thing
came to my mind. It looks like one app can have 2 connections to web
services. How about if I create a thread from the application and make async
web service calls? Would the thread make the connection using the app's
connections or would it get its own 2 connections?
 
Thanks for your response Mache2,

This connection configuration setting is per Application based, that means
for .net application, each app domain will has such as connection
limitation for other remote server. So no matter the connection is created
within a background thread or main thread or even thread pool thread,
it'll occupy the existing connections for that appdomain. For example, in
your application, the button1's calling the async method of
HelloWord1(BeginHelloworld), this call infact executing on a threadpool
thread, but it also occupy your application(appdomain)'s existing
connections to that certain remote machine.

Thanks & Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Thanks,
I have another issue, It seems the if I put a delay for about 100 seconds in
the sync call, I get a time out exception. In the article there is a mention
of httpRuntime. I tried to change execution time to 120 in the web.config
file but I still get the exception. In the client, I also changed
webservice.timeout to 120 also but that didn't make any difference either.
Would you tell me what I have to do in the client and in the server to bump
the time out default?
 
Hi Mache2,

Thanks for your further followup.
I think the Timeout problem you encountered is caused by the "Timeout"
setting at client , are you getting a clientside timeout exception ? We can
check this from the exception's call stack, (the exception's type).

Based on my understanding, when do a sync webservcie call, the timeout is
only determined by two settings(if there is no other component's timeout
affact the webmethod):

1. The httpRuntime's executionTimeout , this is the serverside timeout
setting.

2. The soaphttpclientprotocol's Timeout property, this is the webservice
client proxy's timeout setting.

Also, the Timeout of the SoapHttpClientprotocol is millionsecond based, so
if we want to set 100 seconds as the timeout value , we need to code like:

service.Timeout = 100 * 1000;


#WebClientProtocol.Timeout Property
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfsystemwebservicesprotocolswebclientprotocolclasstimeouttopic.asp

Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Steven,
Yes, I had a time out in the client. But finally I was able to extend the
default time out period by setting the timeout property of the web service
proxy.
I also figured out why httpruntime was not effective. In the web.config file
<compilation debug="true"/> should be false. Then this attribute is active as
well.

Thanks for your help
 
You're welcome Mache2,

Yes, to make serverside httpRuntime's executionTimeout work, the app's
web.config should turn off "debug" in the <compilation>

Also, we are not recommended to set the executionTimeout value to less than
1.5 minutes, if the timeout value is too small, there will have a delay at
runtime, the delay will range from 5--15 seconds.

Anyway, glad that you've got it work now. Good Luck!

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Back
Top