Thread Synchronization C# --> C++

Hello

I have a little native dll written in C++. I call it's functions from C#, but I have some problems that I can't afford. I have no unerstanding in multi-threading at all, so your help will be appreciated.

I have a C# class which uses BackgroundWorker. It calls the dll's function to determine some changes and if one found, it must trigger associated event. But the problem is that I call Connect() function from the BackgroundWorker's DoWork event (in some seconds interval) which is said not to be Thread Safe and I call the same function from Main Thread, so some times an AccessViolationException raises saing "Attempted to read or write protected memory. This is often an indication that other memory is corrupt.".

So my question is how can I fix this problem

thanks in advance.




Answer this question

Thread Synchronization C# --> C++

  • Jose M. Ladero

    Thanks for your fast reply.

    I can use InvokeRequired and Invoke only on controls. My class is not a control, it is a class library. is it possible to call the Connect() function from a class which is not a control using Invoke

    thanks



  • zdjray

    Can you post the relevant code


    sure.

    here is the dllimport


    [DllImport("cashcard.dll", CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.Cdecl, ExactSpelling = false)]
    static extern bool Connect();

     


    I have a property CardInReader which trys to connect to the device. if succeds the card is in the reader. this property calls Connect() function from another thread(BackgroundWorker's DoWork event).


    public bool CardInReader
    {
        get
        {
            return Connect();
        }
    }

     


    and I have OpenReader function to connect to the device


    public void OpenReader()
    {
        if (EstablishContext() == false)
        {
            throw new CashCardException("Error. Can not create context! \n" +
                "SCardEstablishContext returned an error");
        }
    }

    if (ListReaders() == false)
    {
        CashCardCloseReader();

        throw new CashCardException("Error. Can not find card reader! Connect the reader and try again \n" +
            "SCardEstablishContext returned an error");
    }

    if (Connect() == false)
    {
        CashCardCloseReader();

        throw new CashCardException("Error. Could not connect to the card reader. make sure " +
            "the card is in the reader.\n" + "SCardConnect returned an error");
    }

    ResetConnectedProperty(false);

    WasConnected = true;

    if (OnConnect != null)
    {
        OnConnect();
    }

    System.Threading.Thread.Sleep(1000);

     


    I check the CardInReader property simultaniously and because I do it from another thread I think that thats the cause of Exception.

    here's the Connect() function's code


    BOOL EXPORT Connect()
    {
        //HANDLE hMutex = CreateMutex(NULL, false, "CashCardMutex");

        LONG lReturn;
        DWORD dwAP;

        BOOL mRelease = FALSE;

        if(!pSysVar->hSC)
        {
            EstablishContext();
            ListReaders();

            mRelease = TRUE;
        }

        lReturn = SCardConnect(pSysVar -> hSC, (LPCSTR)pSysVar -> bReaders, SCARD_SHARE_SHARED,

        SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &pSysVar -> hCardHandle, &dwAP);

        Sleep(10);

        if (lReturn != SCARD_S_SUCCESS)
        {
            return FALSE;
        }   

        if ((dwAP != SCARD_PROTOCOL_T0) || (!pSysVar -> hCardHandle))
        {
            return FALSE;
        }

        WORD lRet = SetCardInReader(pSysVar, TRUE);

        if(lRet == FALSE)
        {
            return FALSE;
        }

        lRet = SetCardReady(pSysVar, TRUE);

        if(lRet == FALSE)
        {
            return FALSE;
        }

        pSysVar -> fReaderOK = TRUE;

        if(mRelease)
        {
            CashCardCloseReader();
        }

        //ReleaseMutex(hMutex);
        return TRUE;
    }

     


    thanks for your help :)


  • tonic999

    You can check if invoke is required, here is a little example:



    public void Connect()
    {
    if( InvokeRequired )
    {
    // Invoke was required, so invoke this method.
    MethodInvoker method = new MethodInvoker( Connect );
    Invoke( method );
    return;
    }

    // TODO: Add normal code here.
    }



  • Kramish

    But the event is handled on a control

    Can you post the relevant code


  • Charles Aimer

    well, when I call the CloseReader() function.

    the function looks like this

    public void CloseReader()

    {

    CashCardCloseReader();

    if (OnDisconnect != null)

    OnDisconnect(CardReason.UserClosedConnection);

    ResetConnectedProperty(true);

    this.IsLogged = false;

    }

    it calls the CashCardCloseReader() in the native dll.

    void EXPORT CashCardCloseReader()

    {

    LONG lReturn;

    pSysVar->fReaderOK = FALSE;

    if (pSysVar -> hSC)

    {

    if (pSysVar -> hCardHandle)

    lReturn = SCardDisconnect(pSysVar -> hCardHandle, SCARD_LEAVE_CARD);

    lReturn = SCardReleaseContext(pSysVar -> hSC);

    pSysVar -> hSC = 0;

    pSysVar -> hCardHandle = 0;

    pSysVar -> fCardInReader = 0;

    pSysVar -> fCardReady = 0;

    pSysVar -> fCardReadyAndValid = 0;

    pSysVar -> dwTmpAtrLen = 0;

    }

    }

    I think that because I check the CardInReader property in loop, which calls the Connect() function, the CashCardCloseReader() and Connect() function executes simultaniously.



  • Zartor

    You can safelly invoke your events when needed, but it is better to make the method that handles the event safe as i posted in my first post.

    I don't know on wish line you get the exception, but if you want to make your events safe:


    if( OnDisconnect != null )
    {
    Control control = OnDisconnect.Target as Control;

    if( control != null && control.InvokeRequired )
    {
    object[] args = new object[]
    {
    CardReason.UserClosedConnection
    };

    control.Invoke( OnDisconnect, args );
    }
    else
    {
    OnDisconnect(CardReason.UserClosedConnection);
    }
    }




  • Ted Glaza

    Thank you for your fast and clear replies!

    Happy coding!


  • Ikuko O.

    thanks a lot. you can not imagin how your post was helpful for me :) I've been torturing for that piece of code for 1 month :) thanks again and good luck :)

  • Jon_The_Coder

    Thanks for the code, now where do you get the exception

    Note: I reformatted your post, added quote and code tags.


  • Thread Synchronization C# --> C++