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.

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
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
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
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
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
Happy coding!
Ikuko O.
Jon_The_Coder
Note: I reformatted your post, added quote and code tags.