C#task async等待智能卡 - UI线程被阻止

时间:2013-12-12 05:43:00

标签: c# multithreading task-parallel-library async-await smartcard

我是C#的新手,我正在尝试使用任务异步等待WinsForm GUI。我已经阅读了很多关于它的教程,但是所有这些教程都以不同的方式实现了任务。有些任务使用函数,而其他任务只是将代码放入执行。有些使用Task.Run()或只是等待。此外,我所见过的所有示例都包含在UI类中。我试图运行在我的UI中的类中的函数。我现在真的很困惑,不知道对错是什么。

我尝试做的是使用SpringCard API / PC / SC库将文件写入EEPROM。我将文件解析为数据包并将其写入智能卡。我还想更新状态标签和进度条。很多事情都可能出错。我在智能卡中设置了标志,现在我只是一个循环运行,直到它读取某个标志,如果它永远等待标志,这显然会使程序停止。

我想我只是对如何设置它感到困惑。救命。我尝试过使用任务。到目前为止,这是我的代码。

/* Initialize open file dialog */
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;
            ofd.Filter = "BIN Files (.bin)|*.bin|HEX Files (.hex)|*.hex";
            ofd.InitialDirectory = "C:";
            ofd.Title = "Select File";

            //Check open file dialog result
            if (ofd.ShowDialog() != DialogResult.OK)
            {
                if (shade != null)
                {
                    shade.Dispose();
                    shade = null;
                }
                return;
            }

            //progform.Show();
            Progress<string> progress = new Progress<string>();
            file = new ATAC_File(ofd.FileName);

            try
            {
                cardchannel.DisconnectReset();
                Task upgrade = upgradeASYNC();

                if(cardchannel.Connect())
                {
                    await upgrade;
                }
                else
                {
                    add_log_text("Connection to the card failed");

                    MessageBox.Show("Failed to connect to the card in the reader : please check that you don't have another application running in background that tries to work with the smartcards in the same time");
                    if (shade != null)
                    {
                        shade.Dispose();
                        shade = null;
                    }

                    cardchannel = null;
                }
        }


    private async Task upgradeASYNC()
        {
            int i = 0;
            int totalpackets = 0;

            add_log_text("Parsing file into packets.");
            totalpackets = file.parseFile();

            /*progress.Report(new MyTaskProgressReport
            {
                CurrentProgressAmount = i,
                TotalProgressAmount = totalpackets,
                CurrentProgressMessage = "Sending upgrade file..."
            });*/

            ST_EEPROMM24LR64ER chip = new ST_EEPROMM24LR64ER(this, cardchannel, file, EEPROM.DONOTHING);

            bool writefile = chip.WriteFileASYNC();
            if(writefile)
            {
                add_log_text("WRITE FILE OK.");
            }
            else
            {
                add_log_text("WRITE FILE BAD.");
            }

        }

在文件类中:

public int parseFile()
        {
            FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            FileInfo finfo = new FileInfo(filename);

            int readbytecount = 0;
            int packetcount = 0;
            int numofbytesleft = 0;
            byte[] hash = new byte[4];
            byte[] packetinfo = new byte[4];
            byte[] filechunk = null;

            /* Read file until all file bytes read */
            while (size_int > readbytecount)
            {
                //Initialize packet array
                filechunk = new byte[MAXDATASIZE];

                //read into byte array of max write size
                if (packetcount < numoffullpackets)
                {
                    //Initialize packet info array
                    packetinfo[0] = (byte)((size_int + 1) % 0x0100); //packetcountlo
                    packetinfo[1] = (byte)((size_int + 1) / 0x0100); //packetcounthi
                    packetinfo[2] = (byte)((packetcount + 1) / 0x0100); //packetcounthi
                    packetinfo[3] = (byte)((packetcount + 1) % 0x0100); //packetcountlo

                    //read bytes from file into packet array
                    bytesread = br.Read(filechunk, 0, MAXDATASIZE);

                    //add number of bytes read to readbytecount
                    readbytecount += bytesread;
                }
                //read EOF into byte array of size smaller than max write size
                else if (packetcount == numoffullpackets)
                {
                    //find out how many bytes left to read
                    numofbytesleft = size_int - (MAXDATASIZE * numoffullpackets);

                    //Initialize packet info array
                    packetinfo[0] = (byte)((size_int + 1) / 0x0100); //packetcounthi
                    packetinfo[1] = (byte)((size_int + 1) % 0x0100); //packetcountlo
                    packetinfo[2] = (byte)((packetcount + 1) / 0x0100); //packetcounthi
                    packetinfo[3] = (byte)((packetcount + 1) % 0x0100); //packetcountlo

                    //Initialize array and add byte padding, MAXWRITESIZE-4 because the other 4 bytes will be added when we append the CRC
                    //filechunk = new byte[numofbytesleft];
                    for (int j = 0; j < numofbytesleft; j++)
                    {
                        //read byte from file
                        filechunk[j] = br.ReadByte();

                        //add number of bytes read to readbytecount
                        readbytecount++;
                    }

                    for (int j = numofbytesleft; j < MAXDATASIZE; j++)
                    {
                        filechunk[j] = 0xFF;
                    }
                }
                else
                {
                    MessageBox.Show("ERROR");
                }

                //calculate crc32 on byte array
                int i = 0;
                foreach (byte b in crc32.ComputeHash(filechunk))
                {
                    hash[i++] = b;
                }

                //Append hash to filechunk to create new byte array named chunk
                byte[] chunk = new byte[MAXWRITESIZE];
                Buffer.BlockCopy(packetinfo, 0, chunk, 0, packetinfo.Length);
                Buffer.BlockCopy(filechunk, 0, chunk, packetinfo.Length, filechunk.Length);
                Buffer.BlockCopy(hash, 0, chunk, (packetinfo.Length + filechunk.Length), hash.Length);

                //Add chunk to byte array list
                packetcount++;
                PacketBYTE.Add(chunk);
            }

            parseCMD();

            return PacketBYTE.Count;
        }

在EEPROM类中:

public bool WriteFileASYNC()
    {
        int blocknum = ATAC_CONSTANTS.RFBN_RFstartwrite;
        byte[] response = null;
        CAPDU[] EEPROMcmd = null;
        int packetCount = 0;

        log("ATTEMPT: Read response funct flag.");
            do
            {
                StopRF();
                Thread.SpinWait(100);
                StartRF();
                log("ATTEMPT: Write function flag.");
                while (!WriteFlag(ATAC_CONSTANTS.RFBN_functflag, EEPROM.UPLOADAPP)) ;
            } while (ReadFunctFlag(ATAC_CONSTANTS.RFBN_responseflag, 0) != EEPROM.UPLOADAPP);  

            for (int EEPROMcount = 0; EEPROMcount < file.CmdBYTE.Count; EEPROMcount++)
            {
                string temp = "ATTEMPT: Write EEPROM #" + EEPROMcount.ToString();
                log(temp);
                EEPROMcmd = file.CmdBYTE[EEPROMcount];

                while (EEPROMcmd[blocknum] != null)
                {
                    if (blocknum % 32 == 0)
                    {
                        string tempp = "ATTEMPT: Write packet #" + packetCount.ToString();
                        log("ATTEMPT: Write packet #");
                        packetCount++;
                    }

                    do
                    {
                        response = WriteBinaryASYNC(EEPROMcmd[blocknum]);
                    } while (response == null);

                    blocknum++;
                }

                log("ATTEMPT: Write packet flag.");
                while (!WriteFlag(ATAC_CONSTANTS.RFBN_packetflag, ATAC_CONSTANTS.RFflag)) ;

                log("ATTEMPT: Write packet flag.");
                do
                {
                    StopRF();
                    Thread.SpinWait(300);
                    StartRF();

                } while (!ReadFlag(ATAC_CONSTANTS.RFBN_packetresponseflag, ((blocknum/32) - 1)*(EEPROMcount+1)));

                blocknum = ATAC_CONSTANTS.RFBN_RFstartwrite;
            }

            return true;
        }

1 个答案:

答案 0 :(得分:-1)

任务是线程。

当你这样写:

Task upgrade = upgradeASYNC();

您只是在新线程中执行upgradeASYNC。

当你这样写:

 await upgrade;

您只是在等待新线程完成(在转到下一条指令之前)。

这个方法

private async Task upgradeASYNC()

仅返回Task对象,因为您添加了async关键字。但在这种方法的体内,没有等待。所以它只是同步运行,就像任何线程工作一样。

我没有时间重写你的代码,我让那个给另一个stackoverflow用户。你应该学习并努力工作;)