0

Silverlight4アプリケーションの問題。このアプリケーションでは、すべてのクライアントセッションが、DLLを呼び出す個別のプロセスを作成します。

DLLとの通信は、次のコールスタックのように構築されます(2つの関数の場合:1つは機能し、もう1つは機能しません)。

DLLには2つの関数があります(どちらも正常に機能します)。

extern "C" BOOL __stdcall DocRunExternPageDividions(const char *docId, int num_form, int PageNum, int *Vcols, int **Vvalues, int *Hcols, int **Hvalues)
{
    LOG_START_FUNCTION
    BOOL res = 1;
    __try {
        res = DocRunExternPageDividions1(docId, num_form, PageNum, Vcols, Vvalues, Hcols, Hvalues);
    }
    __except(ExFilter(GetExceptionInformation()))
    {
        AfxThrowUserException();
    }
    LOG_STOP_FUNCTION
    return res;
}


extern "C" BOOL __stdcall DocRunExternPageBreakRects(const char *docId, int num_form, int PageNum)
{
    LOG_START_FUNCTION
        BOOL res = 1;
    __try {
        res = DocRunExternPageBreakRects1(docId, num_form, PageNum);
    }
    __except(ExFilter(GetExceptionInformation()))
    {
        AfxThrowUserException();
    }
    LOG_STOP_FUNCTION
        return res;
}

この関数を呼び出すために、サーバーには2つのデリゲートがあります。

private delegate void DocRunExternPageBreakRectsDelegate(string docId, int DocNum, int PageNum);

private delegate void DocRunExternPageDividionsDelegate(
    string docId, int DocNum, int PageNum, out int Vcols, out IntPtr VoutArray, out int Hcols,
    out IntPtr HoutArray);

... 2つのデリゲートインスタンスと対応する関数:

    private DocRunExternPageBreakRectsDelegate DocRunExternPageBreakRectsD;
                DocRunExternPageBreakRectsD =
                Marshal.GetDelegateForFunctionPointer(ptrDocRunExternPageBreakRects,
                                                      typeof (DocRunExternPageBreakRectsDelegate)) as
                DocRunExternPageBreakRectsDelegate;

    private DocRunExternPageDividionsDelegate DocRunExternPageDividionsD;
                DocRunExternPageDividionsD =
                Marshal.GetDelegateForFunctionPointer(ptrDocRunExternPageDividionsD,
                                                      typeof (DocRunExternPageDividionsDelegate)) as
                DocRunExternPageDividionsDelegate;

    public void DocRunExternPageDividions(string docId, int DocNum, int PageNum, out int[] vert, out int[] horz) {
        IntPtr VoutArray, HoutArray;
        int vcols, hcols;
        DocRunExternPageDividionsD(docId, DocNum, PageNum, out vcols, out VoutArray, out hcols, out HoutArray);
        marshal(VoutArray, out vert, vcols);
        marshal(HoutArray, out horz, hcols);
    }

    public void DocRunExternPageBreakRects(string docId, int DocNum, int PageNum) {
        DocRunExternPageBreakRectsD(docId, DocNum, PageNum);
    }

これらの各関数はここで呼び出されます(サーバーコード):

    public bool PageBreakRects(string docId, int DocNum, int PageNum, out int[] vert, out int[] horz) {
        bool result;
        vert = null;
        horz = null;
        Program.WriteUserMessage("Called PageBreakRects(" + docId + ", " + DocNum + ", " + PageNum + ")");
        try {
            DocRunExternPageBreakRects(docId, DocNum, PageNum);
            DocRunExternPageDividions(docId, 0, PageNum, out vert, out horz);
            result = true;
        } catch (Exception ex) {}
        return result;
    }

    public bool GetPageDividions(string docID, int Id, int pageNumber, out int[] vert, out int[] horz) {
        bool result = false;
        vert = null;
        horz = null;
        try {
            DocRunExternPageDividions(docID, Id, pageNumber, out vert, out horz);
            result = true;
        } catch (Exception) {}
        return result;
    }

それらのそれぞれ-ここで呼び出されます:

    public DocDividionsResult PageBreakRects(string docID, int DocNum, int pageNumber) {
        var result = new DocDividionsResult();
        int[] vert;
        int[] horz;
        result.Data = new List<object> { Program.DllWrapper.PageBreakRects(docID, DocNum, pageNumber, out vert, out horz) };
        result.Vert = vert;
        result.Horz = horz;
        return result; 
    }

    public DocDividionsResult GetPageDividions(string docID, int formId, int pageNumber) {
        var result = new DocDividionsResult();
        int[] vert;
        int[] horz;
        result.Data = new List<object>
                      {Program.DllWrapper.GetPageDividions(docID, formId, pageNumber, out vert, out horz)};
        result.Vert = vert;
        result.Horz = horz;
        return result;
    }

次に-ラムダ式内:

    public bool GetPageDividions(string docID, int formId, int pageNumber, out int[] vert, out int[] horz) {
        bool result = false;
        int []localVert = null;
        int []localHorz = null;

        if (_wp != null) {
            if (Service<IWPCommunication>.Use(TestService =>
            {
                TestService.Test(UserId);
            },
            WPService =>
            {
                DocDividionsResult br = WPService.GetPageDividions(docID, formId, pageNumber);
                if (br != null && br.Data != null && br.Data.Length == 1)
                {
                    result = (bool)br.Data[0];
                    localVert = br.Vert;
                    localHorz = br.Horz;
                }
            }, Id, FS) == 0)
            {
        ...
                result = false;
            }
        }
        vert = localVert;
        horz = localHorz;
        return result;
    }

    public bool PageBreakRects(string docId, int DocNum, int PageNum) {
        bool result = false;
        if (_wp != null)
        {
            if (Service<IWPCommunication>.Use(TestService =>
            {
                TestService.Test(UserId);
            },
            WPService =>
            {
                DocDividionsResult br = WPService.PageBreakRects(docId, DocNum, PageNum);
                if (br != null && br.Data != null && br.Data.Length == 1) {
                    result = (bool)br.Data[0];
                }
            }, Id, FS) == 0)
            {
        ...
                result = false;
            }
        }
        return result;
    }

「使用」機能(上記で使用):

    public static int Use(UseServiceDelegate<T> codeTest, UseServiceDelegate<T> codeBlock, string SessionId, FileStream fs, bool throwException) {
        IClientChannel texy = (IClientChannel)_testFactory.CreateChannel(new EndpointAddress("net.pipe://localhost/X2WPServiceUID" + SessionId));
        IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel(new EndpointAddress("net.pipe://localhost/X2WPServiceUID" + SessionId));
        int returnCode = 0;
        try {
            if (codeTest != null) {
                codeTest((T)texy);
                texy.Close();
            }
            returnCode = 1;
            if (codeBlock != null) {
                codeBlock((T)proxy);
                proxy.Close();
            }
            returnCode = 2;
        } catch(Exception e) {
            if (returnCode == 1 && throwException)
                throw e;
        } finally {
            if (returnCode == 0 && codeTest != null)
                texy.Abort();
            else if (returnCode == 1 && codeBlock != null)
                proxy.Abort();
        }
        return returnCode;
    }

サーバー側で例外が発生するため、クライアント通信は省略されます。GetPageDividions関数は正常に機能しますが、PageBreakRectsにバグがあります-そうではありません:行DocDividionsResult br = WPService.PageBreakRects(docId、DocNum、PageNum); 次の例外をスローします。

"The message with Action 'http://tempuri.org/IWPCommunication/PageBreakRects' 
cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher.
This may be because of either a contract mismatch (mismatched Actions between sender and receiver) 
or a binding/security mismatch between the sender and the receiver.  
Check that sender and receiver have the same contract and the same binding 
(including security requirements, e.g. Message, Transport, None)."

さらに悪いことに、関数PageBreakRectsで次を置き換えた場合:DocDividionsResult br = WPService.PageBreakRects(docId、DocNum、PageNum); DocDividionsResultを使用br=WPService.GetPageDividions(docID、formId、pageNumber); その後、例外はスローされません。

4

1 に答える 1

1

最初から開始したかどうかはわかりませんが、投稿したコードのいずれもエラーの原因ではないことを期待しています。このエラーは、Web 構成の system.serviceModel セクションにエラーがあるため、クライアント (silverlight) からの Web サービスの呼び出しに問題があることを意味します。多くの場合、サービス参照を更新するだけで修正できます。

アプリを Visual Studio でローカルに実行してみて、サービス参照をサーバーにインストールしたサービスに向けます (サービス参照を右クリックし、[サービス参照の構成] を選択して、サーバー上のサービスの場所に対応するように URl を変更します)。この構成で既に開発/テストを行っている場合は、サービス参照を右クリックして、[サービス参照の更新] を選択してみてください。

于 2012-08-29T19:23:56.813 に答える