5
\$\begingroup\$

My definition of monkey testing is basically playing with a program in as if I was a monkey (press every button, unplug things, go in the wrong order..etc etc)

So I made a rather simple SmartCard library that when I "enable" it it just polls the smart card reader for a card, and reports back information. see code

private void CardStatusChange()
{
    readerState[0].dwCurrentState = SCardState.SCARD_STATE_UNAWARE;
    while (run)
    {
        System.Threading.Thread.Sleep(100);
        if (SCWrapper.SCardGetStatusChange(scHandle, UInt32.MaxValue, readerState, 1) == SCardFunctionReturnCodes.SCARD_S_SUCCESS)
        {
            readerState[0].dwCurrentState = readerState[0].dwEventState;
            SendCardStatus(readerState[0].dwEventState);
        }
    }
}

private void SendCardStatus(SCardState sCardState)
{
        //case SCardState.SCARD_STATE_UNAWARE:
        //case SCardState.SCARD_STATE_IGNORE:
        //case SCardState.SCARD_STATE_CHANGED:
        //case SCardState.SCARD_STATE_UNKNOWN:
        //case SCardState.SCARD_STATE_UNAVAILABLE:
        //case SCardState.SCARD_STATE_EMPTY:
    if (HasStateMask(sCardState, SCardState.SCARD_STATE_EMPTY))
        OnCardUnplugged(); //fire event
        //case SCardState.SCARD_STATE_PRESENT:
    if (HasStateMask(sCardState, SCardState.SCARD_STATE_PRESENT))
    {
        OnCardPluggedIn(); //fire event
        SendCardATR(readerState[0].rgbAtr); //fire event
    }
        //case SCardState.SCARD_STATE_ATRMATCH:
    OnATRMatch(HasStateMask(sCardState, SCardState.SCARD_STATE_ATRMATCH));
        //case SCardState.SCARD_STATE_EXCLUSIVE:
        //case SCardState.SCARD_STATE_INUSE:
    OnCardInUse(HasStateMask(sCardState, SCardState.SCARD_STATE_INUSE));
        //case SCardState.SCARD_STATE_MUTE:
        //case SCardState.SCARD_STATE_UNPOWERED:
}

private bool HasStateMask(SCardState theValue, SCardState theMask)
{
    return ((theValue & theMask) == theMask);
}

This part works as expected in that while my thread is running I can plug in and unplug a smartcard as often and as quickly as I want without problem. What I'm struggling with is the Threading portion of it. Visual Studio screams at me for using suspend and I found a bug when using suspend in my thread so I am taking that out (in other words don't comment on that) but this is how I "open" and "enable" my smart card

public override bool Open()
{
    readerThread = new Thread(CardStatusChange);
    //code here to setup the smart card
    return true;
}

public override bool Enable()
{
    run = true;
    //thread start checking for card events
    switch (readerThread.ThreadState)
    {//this is probably a mistake
        case ThreadState.AbortRequested:
            break;
        case ThreadState.Aborted:
            break;
        case ThreadState.Background:
            break;
        case ThreadState.Running:
            break;
        case ThreadState.StopRequested:
            break;
        case ThreadState.Stopped:
            break;
        case ThreadState.SuspendRequested:
            break;
        case ThreadState.Suspended:
            readerThread.Resume();//TODO remove

            break;
        case ThreadState.Unstarted:
            readerThread.Start();

            break;
        case ThreadState.WaitSleepJoin:
            break;
        default:
            break;
    }

    return true;
}
public override void Disable()
{
    run = false;
    readerThread.Suspend(); //TODO remove
}

I've never been too good at threading, but I do need this as a thread (I think I do atleast I am open to other ideas). So how should I really Enable and Disable? I used to just set run to true or false, but my monkey testing showed that this doesn't always work and sometimes Windows would cry that it can't start a running thread... SO I dunno what to do. Any thoughts?

\$\endgroup\$
  • \$\begingroup\$ I think I found the answer. It appears to be work. On the Disable instead of readerThread.Suspend() I change it to readertThread.Join(). Then I just check for the Unstarted flag for Enable and fire it up. So far it is working good with no hicups. still have further testing. \$\endgroup\$ – Robert Snyder Apr 19 '13 at 21:21
  • 1
    \$\begingroup\$ Can you post the answer you found as an answer? This will help future users. \$\endgroup\$ – Ryan Gates Jun 14 '13 at 15:36
  • \$\begingroup\$ @RyanGates Sure can... :) \$\endgroup\$ – Robert Snyder Jun 14 '13 at 16:07
3
\$\begingroup\$

As requested by Ryan Gates I should post my results. I don't remember the entire scope of what i did, but I do know where the code is :)

So the basics are that I want the thread to be able to exit without causing any strange hicups if the user decides to use my library incorrectly. So I made the thread turn into a background thread. I was able to remove the ugly switch statement and just check the appropriate bits are set to make sure I can start my thread (basically only allows one thread to read a smart card instead of multiple reading the same card)

On Disable what I did was set my flag to kill the loop in my readerThread thread. I then wait for it to exit by using the thread.Join Clear as mud??? I can try to clear up more if anyone has questions.

public override bool Open()
{
    //Code to setup SmartCard

    readerThread = new Thread(CardStatusChange);
    readerThread.IsBackground = true;

    return true;
}
public override bool Enable()
{
    run = true;
    //thread start checking for card events
    Globals.tracer.TraceInformation("Checking Thread State:{0}", readerThread.ThreadState);
    var startable = (readerThread.ThreadState & ThreadState.Unstarted);
    if (startable > 0)
        readerThread.Start();

    return true;
}
public override void Disable()
{
    run = false;
    if(readerThread.ThreadState == ThreadState.Unstarted)
        readerThread.Join();
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.