C# 任务异步等待智能卡 - UI 线程阻塞

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

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

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

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

/* 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;
        }

最佳答案

任务是线程。

当你这样写的时候:

Task upgrade = upgradeASYNC();

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

当你这样写的时候:

 await upgrade;

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

还有这个方法

private async Task upgradeASYNC()

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

我没有时间重写你的代码,我把它交给了另一个 stackoverflow 用户。你应该更加努力地学习和工作;)

关于C# 任务异步等待智能卡 - UI 线程阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20535904/

相关文章:

java - 在 Vaadin 7 中调用 VaadinSession getAttribute 时需要锁定

c# - 新线程()和线程池?

c# - Parallel.Invoke 什么时候有用?

c# - c#中显式接口(interface)实现和隐式接口(interface)实现有什么区别

c# - Mysqldump 在查询内不起作用

c# - 根据数组元素对数组的每 500 个元素进行分组

python - Python 中的线程——我错过了什么?

c# - 为什么我没有收到 "Cross-thread operation not valid"错误

c# - 阶乘的答案不相同(平行和正常)

c# - iTextSharp HTMLWorker.ParseToList() 抛出 NullReferenceException