我是C#的新手,目前正致力于支持密码键盘的后端代码。基本上,我的代码
OpenDevice() -> RequestPIN()
-> key in PIN on PIN PAD -> GetResultPIN()
-> ConsolePrintOutPIN() -> Print keyed PIN on the Console
我不知道如何为此编写线程,因此一旦在PIN之后在设备上点击“Enter键”,系统将自动滚动到功能GetResultPIN()
。因此,根据我的基本知识,我使用Console.ReadLine()
编写了以下代码来分隔每个过程:
static void Main(string[] args)
{
// 1. Open PIN Pad device
OpenDevice();
Console.ReadLine();// to hold up from the previous procedure, it is *not* for input data purpose
// 2. Request PIN from PIN Pad device.
// On the PIN Pad device, it reads:
// "Key in the PIN: "
RequestPIN();
Console.ReadLine();// to hold up from the previous procedure, it is *not* for input data purpose
// 3. get PIN from the device
GetResultPIN();
// 4. Print out on the Console
ConsolePrintOutPIN();
Console.ReadLine();// to hold up from the previous procedure, it is *not* for input data purpose
}
问题:任何人都可以向我提供有关如何使用线程/事件/代理的任何建议,以避免使用Console.ReadLine()
吗?
如上所述,Console.ReadLine()
仅用于停止程序(抱歉我以这种方式使用它的天真......)一旦我使用Console.ReadLine()
,RequestPIN()
和GetResult()
,系统至少会等待我从PIN PAD输入密码(通过USB连接到计算机,不是从密钥板),然后我会点击任何密码通过Console.ReadLine()
和GetResultPIN()
的键盘上的键可以从PIN Pad获取我的PIN号码.....整个程序现在可以使用,它不是客户准备好的,因为它非常不稳定,由于我添加了Console.ReadLine()
而无法流动.....
理想情况下,所有方法都会一起流动。打开设备后,{PIN码屏幕}上会显示RequestPIN()
,要求输入密码,有人可以输入密码并在密码键盘上输入,它会自然流向GetResultPIN()
并读取结果,然后它在控制台上打印PIN ......“
或
如果此人未输入密码,设备将等待30秒并直接转至GetResultPIN()
并在控制台上打印出“0000”
我已经查询了踩踏和委托,但我不确定如何在这种情况下使用它们....谢谢!
参考: RequestPin()和GetResultPIN列在下面:
mIPAD.requestPIN(waitTime, pinMsg, minLen, maxLen, tone, option, ",");
//This function wraps device command 0x04.
//It directs the device to prompt the user to enter a PIN
//by displaying one of five predetermined messages and playing
// a specified sound.
//The messages on the device’s screen look like the figures below.
//The event associated with this function is
//OnPINRequestCompleteEvent.
waitTime:设备应等待用户开始输入PIN的时间
pinMsg:显示为用户提示的消息,例如“输入PIN”,“重新输入PIN”,“验证PIN”等
minLen和maxLen:PIN的最小长度和最大长度
音:嘟嘟声选项
选项:验证PIN,不验证PIN,ISO0 FOrmat,ISO3格式
输出为:整数,0:成功,非零:错误
public void GetResultPIN()
{
StringBuilder sb = new StringBuilder();
sb.Append(mIPAD.pin.KSN);
// Key Serial Number:
//a given number from the device, unique for each device
sb.Append("," + mIPAD.pin.EPB);
// EPB: encryption of PIN after Dubpt TripleDES,
// essentially, EPB is PIN
sb.Append("," + mIPAD.getStatusCode());
//status code: Zero is good/done
// None-Zero is Error
sb.Append("\r\n");
result = sb.ToString();
}
基本上,GetResultPIN()返回一个随机代码字符串,例如:
PIN成功时9A00030000047A2000AB,AD781711481B08A2,0
。如果跳过引脚输入部分,它将返回,,0
。
答案 0 :(得分:2)
真的很难知道如果没有可以玩的硬件,这是否会起作用......
这是我设想它的工作方式:
static void Main()
{
OpenDevice();
RequestPIN();
if (GetResultPIN())
{
// do something with the PIN:
var pin = mIPAD.pin.EPB;
// ...
}
else
{
Console.WriteLine("0000");
}
}
public static bool GetResultPIN()
{
TimeSpan timeout = TimeSpan.FromSeconds(30);
System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();
SW.Start();
while (mIPAD.getStatusCode() != 0 && SW.Elapsed < timeout)
{
System.Threading.Thread.Sleep(50); // small call to prevent CPU usage ramping to 100%
}
return (mIPAD.getStatusCode() == 0);
}
答案 1 :(得分:1)
您可以将api重写为:
GetResultPIN()
返回值ConsolePrintOutPIN()
在GetResultPIN
中,你需要制作一个ReadYour Pin的任务并等待它。
请参阅:https://msdn.microsoft.com/en-us/library/dd537610(v=vs.110).aspx
您可以这样做:
public string GetResultPIN()
{
StringBuilder sb = new StringBuilder();
sb.Append(mIPAD.pin.KSN);
// Key Serial Number:
//a given number from the device, unique for each device
sb.Append("," + mIPAD.pin.EPB);
// EPB: encryption of PIN after Dubpt TripleDES,
// essentially, EPB is PIN
sb.Append("," + mIPAD.getStatusCode());
//status code: Zero is good/done
// None-Zero is Error
sb.Append("\r\n");
Thread.Sleep(20*1000); // it is in milliseconds
return sb.ToString();
}
答案 2 :(得分:0)
感谢发帖...解决方案仍然不理想......
我还对函数RequestPIN()
做了一些测试。我有以下四种情况:
waitTime
熄灭时更快完成PIN码的输入。
onPINRequestComplete :
OpStatus:0
KSN:9A00030000047A2000C8
EPB:39DED176D3EA40B9
..............................
waitTime
出局时,用户无法完成密码输入
onPINRequestComplete :
OpStatus:2
KSN:00000000000000000000
EPB:0000000000000000
..............................
用户通过按PIN键盘上的“取消X”键取消密码键盘选项。
onPINRequestComplete :
OpStatus:1
KSN:00000000000000000000
EPB:0000000000000000
..............................
在waitTime期间,用户根本没有键入PIN,然后waitTime熄灭。
onPINRequestComplete :
OpStatus:2
KSN:00000000000000000000
EPB:0000000000000000
..............................
因此,方案1和3将要求线程立即唤醒,而2和4将要求线程在waiTime熄灭时唤醒。因此,在Thread.sleep(20*1000)
中使用GetResultPIN()
可以完美地适用于方案2和4.对于1和3,用户必须等待很长时间....
另一方面,我找到了一些关于Event
在 Car.cs :
中using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WaitOnTasksToComplete
{
class Car
{
public event Action OnChange;
private double speed;
public double Speed
{
get { return speed; }
set { speed = value;
if (speed >= 60)
{
if (OnChange != null)
{
OnChange();
}
}
}
}
}
}
在 Program.cs :
中using System;
namespace WaitOnTasksToComplete
{
class Program
{
static void Main(string[] args)
{
Car c = new Car();
c.OnChange += C_OnChange;
c.Speed = 5;
c.Speed = 55;
c.Speed = 65;
c.Speed = 75;
}
private static void C_OnChange()
{
Console.WriteLine("Event fired: Car goes higher than 60 MPH.");
}
}
}
所以,基本上一旦Car.speed
跳到60以上,警报就会显示出来。我正在考虑将这个条件借给我的情况:初始化OpStatus = -999
。在OpStatus=0 or 1
时,继续执行GetResultPIN()
和PrintMessagePIN()
。如果OpStatus=2 or others
,请继续等待......
这只是我的想法....仍然不知道如何实施它....任何相关的想法或建议将不胜感激.......
答案 3 :(得分:0)
OpenDevice()->RequestPIN()->Thread(()=>CheckOpStatus(getResultPIN)) -> Thread.Start()
。在Thread中,设置一个循环来检查OpStatus
的每半秒。根据我之前的帖子,OpStatus
是PIN Pad的输出参数zero- success; non-zero: failure
。也就是说,循环将继续,直到bool condition_WithinWaitTime
或bool condition_NoKeyEvent
中断。发布后,调用getResultPIN
等等......
这是我的源代码,因为PIN输入是我的功能之一,其余的在编程方面具有非常相似的行为(请求 - >手动操作 - >反馈),所以我还包括一个委托变量代表所有功能(刷卡,PIN,签名bla bla)。
static void Main(string[] args)
{
OpenDevice();
EventGetPIN();
}
static void EventGetPIN()
{
myDel getResult = new myDel(GetResultPIN);
Thread thread1 = new Thread(() => CheckOpStatus(getResult));
myDel requestDel = new myDel(RequestPIN); requestDel();
thread1.Start();
}
static void CheckOpStatus(Delegate getResult)
{
int count = 0;
int checkingPeriod = 500;
int totalWaitTime = waitTime * 1000 + offsetTime;
string OpStatus;
string ksnStart = mIPAD.getKSN();
string ksn = ksnStart;
bool condition_WithinWaitTime = true;
bool condition_NoKeyEvent = true;
while (condition_WithinWaitTime & condition_NoKeyEvent)
{
count++;
OpStatus = mIPAD.getStatusCode().ToString();
ksn = mIPAD.getKSN();
//Console.WriteLine(OpStatus);
condition_WithinWaitTime = (count * checkingPeriod) < totalWaitTime;
condition_NoKeyEvent = (ksn == ksnStart);
Thread.Sleep(checkingPeriod);
}
getResult.DynamicInvoke();
}