0

Windows Mobile 6.5、Compact Framework 3.5 用のアプリを開発しています。アプリケーションは、単純なログイン フォームをロードすることから始まります。ログイン フォームが作成されて開かれている間、Web サービスからセットアップ データを取得するための新しいスレッドが作成されます。3 このスレッド内で、同じ Web サービスに対して個別の呼び出しが非同期で行われます。

最初の呼び出しは、会社のリストを取得します。2 番目の呼び出しは、会社に属する場所のリストを取得します。3 番目の呼び出しは、場所と会社に属するユーザーとそのログイン ID のリストを取得します。

各 Web サービスの OnGet***Completed イベントは、返されたデータをローカルの SQLite データベースに保存します。

そのロジックをコンパイルして Visual Studio デバッガーで実行すると、すべてがうまく動作します。アプリが起動し、フォームが表示され、3 つの Web サービス呼び出しが作成されて終了します。ユーザーとしてログインして続行できます。大丈夫です!

例外として、CAB ファイルをビルドし、デバッグに使用するのとまったく同じデバイスにアプリケーションをインストールすると、アプリケーションが 60 秒間待機し、3 つの WebException "The operation has timed-out" エラーが発生し、アプリケーションが強制的に閉じられます。 .

私はこの問題を数日間プレイして調査してきました。Web サービスの構成で最大接続を設定することについてよく読んで、以下に示すようにバインディングを大きな値に設定しました。

<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 に設定しました。

これは、各クラスの新しいインスタンスを作成することによって、3 つの非同期 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 サービス呼び出しを非同期または同期で実行するようにクラスに指示する「非同期」ブール値パラメーターを受け入れます。3 つの 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 Debugger を介してスムーズに実行される理由を理解できませんが、MC55A Motorola デバイスにインストールするとクラッシュします。アプリケーションはエミュレーターでも正常に動作します。

非同期 Web サービス呼び出しの 1 つを削除しようとしましたが、インストールされていれば問題なく動作しましたが、3 つ以上しようとすると失敗します。これは、アプリケーションがデバイスにインストールされたときのように、デフォルトの接続制限が無視され、2 に戻されます。

小説で申し訳ありませんが、Stackoverflowで同様の問題を見たので、十分な情報を提供したかっただけですが、これとまったく同じものはありません. 一度に 1 つの Web サービス接続のみを開いて、これらの呼び出しを同期的に実行できることは認識していますが、このアプリケーションをお客様にとって最速のものにする必要に迫られています。この初期同期操作を同期的に実行することはできますが、将来的には 2 つ以上の Web サービス接続を同時に実行する必要がある場所があることはわかっています。

4

3 に答える 3

1

エラーメッセージをキャッチして保存しているようです。あなたの小説はたまたまそのエラーメッセージが何であるかを述べていましたか?

また、ErrorMessage 文字列値が 1 項目しかないため、上書きされる可能性があることにも気付きました。List(Of String) を試して、エラー メッセージを追加することもできます...少なくとも、これらのエラーのいくつかをキャッチする機会が得られるまでは。

深入りする前に、お使いのデバイスは Web サービスを参照できますか? デバイスがそこを参照できない場合、アプリのコードもそこに到達できません。

于 2013-09-13T19:12:16.137 に答える
0

jp2code に同意します。コードを採用する前に、デバイスが Web サービスに接続できることを確認する必要があります。

デバッガー/エミュレーターで実行する場合と、デバイス上でスタンドアロンで実行する場合の違いは何ですか。デバイスは PC のネットワークに接続されています。

デバイスはサーバーまたは Web サービスに接続できますか? そうでない場合、コードはどのように成功する必要がありますか?

デバイスのネットワーク設定を確認してください。仕事 (Windows 共有) またはインターネット (Web ブラウジング、Web サービス) に接続されていますか? WLAN または GSM を使用していますか? Web サービスのアドレスは? ネットワークが WLAN または公共のインターネット (GSM) からのアクセスをブロックしていませんか?

前述のように、作業コードを変更する前に、まず接続に問題がないことを確認してください。

BWT: デバイスが開発用 PC と同じネットワークに接続された WLAN の場合、TCP/IP を介してリモート デバッグを使用できます: VS2008 は Win Mobile 6.1 デバイスにリモートで接続します。 これを使用すると、デバイスへの ActiveSync/WMDC 接続を切断したときと同じ環境になります。

于 2013-09-14T04:24:21.820 に答える