0

Silverlight 4 应用程序的问题。在此应用程序中,每个客户端会话都会创建一个单独的进程,该进程调用一个 DLL。

与 DLL 的通信是在以下调用堆栈中构建的(对于两个函数:一个工作,另一个 - 不工作)。

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;
}

要调用此函数,服务器有两个委托:

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);

...两个委托实例和相应的功能:

    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;
    }

然后 - 在 lambda 表达式中:

    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

不确定您是否从一开始就开始了,但我希望您发布的代码都不会导致错误。该错误意味着您无法从客户端(silverlight)调用您的 Web 服务,因为您的 Web 配置中的 system.serviceModel 部分存在错误。您通常可以通过刷新您的服务参考来修复它。

尝试在 Visual Studio 中本地运行应用程序并将服务引用指向您安装在服务器上的服务(右键单击服务引用并选择配置服务引用,然后更改 URl 以对应于服务器上的服务位置)。如果您已经在此配置中进行开发/测试,请尝试右键单击服务参考并选择“更新服务参考”。

于 2012-08-29T19:23:56.813 回答