我正在为 Windows Mobile 6.5、Compact Framework 3.5 开发一个应用程序。该应用程序首先加载一个简单的登录表单。在创建并打开登录表单时,会创建一个新线程来从 Web 服务中检索一些设置数据。3 在这个线程中异步地对同一个 Web 服务进行单独的调用。
第一个调用检索公司列表 第二个检索属于公司的位置列表 第三个检索属于位置和公司的用户及其登录 ID 列表
然后每个 Web Service OnGet***Completed 事件将返回的数据保存到本地 SQLite 数据库
当我通过 Visual Studio 调试器编译和运行该逻辑时,一切都运行良好。应用程序启动,显示表单,创建并完成三个 Web 服务调用。我可以以用户身份登录并继续。好的,一切都很好!
除了,当我构建我的 CAB 文件并将应用程序安装在我用于调试的完全相同的设备上时......应用程序等待 60 秒,我得到 3 WebException "The operation has timed-out" 错误并且应用程序被强制关闭.
这几天我一直在玩和研究这个问题。我阅读了很多关于在 Web 服务的配置中设置 Max Connection 的内容,并且我还将绑定设置为较大的值,如下所示:
<add address="*" maxconnection="324"/>
和
<binding name="BasicHttpBinding_IGenericContract" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
在 Windows Mobile 应用程序中启动 Web 服务调用之前,我还将默认连接限制设置为 22。
这是我的代码,它通过创建每个类的新实例来启动所有三个异步 Web 服务调用(类结构如下所示)
'Currently Inside of Initial Synchronize Thread
System.Net.ServicePointManager.DefaultConnectionLimit = 22
Dim syncCompanies As New SyncCompanies(True)
Dim syncLocations As New SyncLocations(True)
Dim syncUsers As New SyncUsers(True)
这是 SyncCompanies 类 New 方法接受一个“异步”布尔参数,该参数告诉类异步或同步执行 Web 服务调用。我想异步运行所有三个 Web 服务。
Public Class SyncCompanies
Private service As New RDScanService.BasicHttpBinding_IGenericContract
'Method that Retrieves the Companies data from the server
Public Sub New(ByVal Asynchronous As Boolean)
DoAsynchronously = Asynchronous
NewCompanies = New Companies(False, False)
Try
IsBusy = True
If DoAsynchronously Then
'Begin the Asynchronous Call
Dim cb As New AsyncCallback(AddressOf onGetCompaniesComplete)
service.BeginGetCompanies(currentSetup.LastCompaniesSync, True, cb, Nothing)
Else
'Perform the Synchronous Call, create a list of Companies and pass to the Execute function for saving
For Each company In service.GetCompanies(currentSetup.LastCompaniesSync, True)
Dim newCompany As New Company(False, False, "")
newCompany.Code = company.Code
newCompany.ReportName = company.ReportName
NewCompanies.Companies.Add(newCompany)
Next
Execute()
IsBusy = False
End If
Catch ex As Exception
service.Abort()
IsBusy = False
Success = False
ErrorVerb = "retrieving companies from server"
ErrorMessage = ex.Message
Finally
Dispose()
End Try
End Sub
Private Sub onGetCompaniesComplete(ByVal ar As IAsyncResult)
'End the Asynchronous Web Service Call and start the Asynchronous Processing
For Each company In service.EndGetCompanies(ar)
Dim newCompany As New Company(False, False, "")
newCompany.Code = company.Code
newCompany.ReportName = company.ReportName
NewCompanies.Companies.Add(newCompany)
Next
ExecuteAsync()
End Sub
Public Sub ExecuteAsync()
'Run the Synchronous method on a new ThreadPool thread
ThreadPool.QueueUserWorkItem(AddressOf DoExecute)
End Sub
Public Sub Execute()
'First determine if the Web Service returned any Companies to save...
If NewCompanies.Companies.Count > 0 Then
NewCompanies.SubmitToDB(True)
If NewCompanies.Success Then
Success = True
Else
Success = False
ErrorVerb = "syncing companies"
ErrorMessage = NewCompanies.Message
End If
End If
IsBusy = False
End Sub
Private Sub DoExecute(ByVal stateInfo As Object)
'Call the Synchronous method on this ThreadPool thread
Execute()
End Sub
Private _newCompanies As Companies
Public Property NewCompanies() As Companies
Get
Return (_newCompanies)
End Get
Set(ByVal value As Companies)
_newCompanies = value
End Set
End Property
Private _success As Boolean
Public Property Success() As Boolean
Get
Return (_success)
End Get
Set(ByVal value As Boolean)
_success = value
End Set
End Property
Private _errVerb As String
Public Property ErrorVerb() As String
Get
Return (_errVerb)
End Get
Set(ByVal value As String)
_errVerb = value
End Set
End Property
Private _errMessage As String
Public Property ErrorMessage() As String
Get
Return (_errMessage)
End Get
Set(ByVal value As String)
_errMessage = value
End Set
End Property
Private _isBusy As Boolean
Public Property IsBusy() As Boolean
Get
Return (_isBusy)
End Get
Set(ByVal value As Boolean)
_isBusy = value
End Set
End Property
Private _doAsynchronously As Boolean
Public Property DoAsynchronously() As Boolean
Get
Return (_doAsynchronously)
End Get
Set(ByVal value As Boolean)
_doAsynchronously = value
End Set
End Property
Protected Sub Dispose()
service.Dispose()
End Sub
结束类
对于我的一生,无法弄清楚为什么我的应用程序可以通过 Visual Studio 调试器顺利运行,但是当安装在 MC55A 摩托罗拉设备上时,它会崩溃。该应用程序在模拟器中也运行良好。
我已经尝试删除 1 个异步 Web 服务调用,并且安装它工作得非常好,但是当我尝试 3 个或更多时,它失败了。几乎就像在设备上安装应用程序时,默认连接限制被忽略并设置回 2。
很抱歉这本小说,只是想确保我提供了足够的信息,因为我在 Stackoverflow 上看到过类似的问题,但没有完全像这个。我确实意识到我可以在一次只打开 1 个 Web 服务连接的情况下同步执行这些调用,但是我们急需使这个应用程序对我们的客户来说是最快的。尽管我可以同步执行此初始同步操作,但我知道在某些地方我需要同时运行 2 个以上的 Web 服务连接。