我对猴子测试的定义基本上是在玩一个程序,就像我是猴子一样(按下每个按钮,拔下插头,输入错误的order..etc等等)。
因此,我制作了一个相当简单的SmartCard库,当我“启用”它时,它只是轮询智能卡读取器的卡片,并报告返回的信息。见代码
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);
}这个部分可以正常工作,因为当我的线程运行时,我可以随心所欲地插入和拔出智能卡。我在挣扎的是它的线程部分。Visual因为我使用挂起而对我大喊大叫,我在我的线程中使用挂起时发现了一个错误,所以我把它拿出来了(换句话说,不要对此发表评论),但这就是我“打开”和“启用”我的智能卡的方式
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
}我从来不太擅长线程处理,但我确实需要将其作为一条主线(我认为我至少对其他想法开放)。那么,我应该如何真正启用和禁用呢?我以前只将run设置为true或false,但我的猴子测试表明,这并不总是有效的,有时Windows会哭着说它无法启动运行的线程……所以我不知道该怎么办。有什么想法吗?
发布于 2013-06-14 15:59:59
根据瑞恩盖茨的要求,我应该发布我的结果。我不记得我做了什么,但我知道代码在哪里:)
因此,基本原则是,如果用户决定不正确地使用我的库,我希望线程能够退出而不会引起任何奇怪的障碍。所以我把这个线程变成了一个后台线程。我能够删除丑陋的开关语句,只需检查适当的位设置,以确保我可以启动线程(基本上只允许一个线程读取智能卡,而不是多次读取同一张卡片)。
在禁用时,我所做的是设置我的标志来杀死我的readerThread线程中的循环。然后,我等待它退出,使用thread.Join清除泥?如果有人有问题我可以尽量澄清。
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();
}https://codereview.stackexchange.com/questions/25266
复制相似问题