0

我正在使用 Visual Studio 2019 构建一个 C# Win Form 应用程序,旨在与智能卡 (ACR 122U) 进行通信。

简而言之:我正在使用的标签类型是阅读器无法识别的被动标签。使用这些标签的唯一方法是将直接命令发送到阅读器内部的芯片。

使用 winscard.dll 我设法做到了。

我正在尝试对标签进行备份:该过程必须读取并存储 128 个块(因此将调用 128 个 SCardControl)。

如果我在 UI 线程中执行此操作,它就像一个魅力(最多 5 秒,在此过程中进程使用 30MB 内存)。但是,如果我尝试在后台线程中执行此操作,则需要很长时间(最少 25 秒,并且在此过程中进程使用 150MB 内存)。

为什么会这样?

编辑:

这是线程的一些代码


//All the DllImport directives:
[DllImport("winscard.dll")]
public static extern int SCardEstablishContext(uint dwScope, IntPtr notUsed1, IntPtr notUsed2, out IntPtr phContext);

[DllImport("winscard.dll", EntryPoint = "SCardListReadersA", CharSet = CharSet.Ansi)]
public static extern int SCardListReaders(IntPtr hContext, byte[] mszGroups, byte[] mszReaders, ref UInt32 pcchReaders);

//... Other working method delcarations

//Declaration of the "slow" method SCardControl
[DllImport("winscard.dll")]
public static extern int SCardControl(IntPtr hCard, int dwControlCode, byte[] lpInBuffer, uint cbInBufferSize, byte[] lpOutBuffer, ref uint cbOutBufferSize, ref int lpBytesReturned);

//... Other declarations.

private void btnBackup_Click(object sender, EventArgs e)
{
    Thread t = new Thread(bgWorker);
    t.Start();
    //bgWorker();
}

public void bgWorker() {
    int res;
    
    uint SystemScope = 2; //From the documentation. Tried both 1 and 2 (User scope and System Scope)
    uint readerNum = 0;
    uint controlMode = 3; //Using SCARD_SHARE_DIRECT as control mode in order to communicate with the reader
    uint protocolToUse = 0; //Using SCARD_PROTOCOL_UNDEFINED as protocol (must use it in order to use SCARD_SHARE_DIRECT)
    int EscapeCode = 3225264; //Suggested by ACR 122 U: Escape code in order to send commands to the reader, computes as SCARD_CTL_CODE(3500) in C.
    string ReadBlockCmd = "FF000000..." //Standard read command in hex for the tag from dtatasheet
    
    IntPtr context = IntPtr.Zero;
    IntPtr simulatedCard = IntPtr.Zero;
    IntPtr protocolEstablished = IntPtr.Zero;

    byte[] readerStream;
    string[] readerList;
    byte[] retStream = new byte[1000];
    uint sizeRetStream = 0;
    int sizeResponse = 0;

    List<string> cardBlocks = new List<string>();

    //NOTE: "res" is always = 0 when everything works. I cutted off the parts where i check the value of "res".

    //Establishing context
    res = SCardEstablishContext(SystemScope, IntPtr.Zero, IntPtr.Zero, out context);

    //Getting the reader list (the return is in "readerStream", with a multistring value)
    res = SCardListReaders(context, null, null, ref readerNum);
    readerStream = new byte[readerNum];
    res = SCardListReaders(context, null, readerStream, ref readerNum);
    readerList = Encoding.ASCII.GetString(readerStream).Split('\0');

    //Connect to the reader
    res = SCardConnect(context, readerList[0], controlMode, protocolToUse, ref simulatedCard, ref protocolEstablished);
    
    /* 
     * Some calls to SCardControl to configure the reader in order to work with my tags
     */
     
    //Backup procedure
    for(int i = 0; i < 128; i++)
    {
        SCardControl(simulatedCard, EscapeCode, HexStrToByteArray(ReadBlockCmd + i.ToString("X2")), (uint)ReadBlockCmd.Length / 2 + 1, retStream, ref sizeRetStream, ref sizeResponse);
        cardBlocks.Add(ByteArrayToHexStr(retStream, sizeResponse));
    }

    //Here it supposed to do the backup on file, but i removed it in order to limit the IO ops
}

如果您注释线程启动部分并取消注释对 bgWorker() 的调用,则该过程将持续 2.1 秒。如果您保持这样(使用线程),则该过程将持续超过 20 秒(无论是在调试模式、发布中、Visual Studio 内部还是外部)。

4

0 回答 0