我发现很多关于Backgroundworker更新进度条的信息,并且我已经编写了许多版本的代码。但是在升级应用程序运行的时候,没有任何版本更新进度条。这里是我已经使用了DoWork的处理程序版本之一:如何获得进度条更新在执行后台工作中运行的应用程序
void worker_DoWork(object sender, DoWorkEventArgs e)
{
updater.updater();
int percents = 0;
// Progress bar
int total = 57;
for (int i = 0; i <= total; i++)
{
System.Threading.Thread.Sleep(100);
percents = (i * 100)/total;
bw.ReportProgress(percents, i);
}
如果我运行更新(我的应用程序)之前ReportProgress(如图所示),更新运行完全,然后进度条的更新从0到100%。如果我在ReportProgress调用之后放置更新程序,则会运行进度栏,然后运行更新程序。如果我用更新程序替换Thread.Sleep行,它将以进度条的0%间隔运行。
实际上是否有可能在后台工作中执行长时间运行的应用程序时更新进度栏?这就是backgroundworker声称的MSDN页面,但他们实际展示的是它运行一系列简短流程(睡眠)而不是一个漫长的过程。我在线上找到的大多数示例都使用这种格式,因此没有提到没有分段到ReportProgress部分的较长时间的运行过程。
我很想知道背景工作者是否能够做到这一点,或者这是一些其他线程类型解决方案的工作。
谢谢!
在看到Tim的回答后,我试图为进度条进度实现EventArg和Handler。
public class FWupdater
{
public string comPort;
public int percentage;
public State state;
public string path;
public const int ACK = 0x79;
public const int NACK = 0x1F;
public class PBProgressEventArgs : EventArgs
{
private int prog;
public int progress
{
set { prog = value; }
get { return this.prog; }
}
}
public class PBProgress
{
public event PBProgressHandler Progress;
public delegate void PBProgressHandler(PBProgress p, PBProgressEventArgs e);
public void Start()
{
if (Progress != null)
{
PBProgressEventArgs progressUpdate = new PBProgressEventArgs();
progressUpdate.progress = 0;
Progress(this, progressUpdate);
}
}
}
然后在主程序中创建一个实例,以便背景工作者可以看到它。
PBProgress progUpdater = new PBProgress();
但我无法从backgroundWorker看到DoWork方法中的进度百分比。
包含更新器代码。
public void updater()
{
// Create a new SerialPort object.
SerialPort _serialPort;
_serialPort = new SerialPort(comPort, 115200, Parity.Even, 8, StopBits.One);
// for state machine
bool _continue = true;
try
{
_serialPort.Open();
if (_serialPort.IsOpen)
{
Console.WriteLine("");
Console.WriteLine("Serial Port is Open");
Console.WriteLine("");
}
else
{
MessageBox.Show("Serial Port is not open. Choose another port.");
}
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
catch (ArgumentOutOfRangeException ex)
{
MessageBox.Show(ex.Message);
}
catch (ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
catch (InvalidOperationException ex)
{
MessageBox.Show(ex.Message);
}
// Move through states until upgrade is complete
while (_continue)
{
switch (state)
{
case State.NORMAL:
// Beginning state for instance of upgrader
break;
case State.WAITING_TO_UPGRADE:
SetUpComm(_serialPort);
state = State.ERASING_FIRMWARE;
break;
case State.ERASING_FIRMWARE:
EraseFlashMemory(_serialPort);
state = State.UPGRADING_FIRMWARE;
break;
case State.UPGRADING_FIRMWARE:
WriteNewAppToFlash(_serialPort);
state = State.UPGRADE_COMPLETE;
break;
case State.UPGRADE_COMPLETE:
JumpToNewApp(_serialPort);
_continue = false;
_serialPort.Close();
break;
default:
break;
} // end SWITCH (state)
} // end WHILE (_continue) - main loop
} // end public void updater()
//
// ---- METHODS -------------------
public void SetUpComm(SerialPort _serialPort)
{
int byte_read = 0x00;
var sevenF = new byte[] { 0x7F };
// Send 0x55 and 0xAA to peripheral input to execute SwitchToBootloader()
var byte1 = new byte[] { 0x55 };
var byte2 = new byte[] { 0xAA };
_serialPort.Write(byte1, 0, 1);
_serialPort.Write(byte2, 0, 1);
// If in bootloader mode, where the boot pins on the board are set,
// the device will be looking to receive 0x7F to establish contact with the host.
// In this case, the bytes to trigger boot load from inside the firmware will be
// ignored and the following 0x7F will serve to trigger comm set-up .
// Wait for acknowledge byte from USART
while (byte_read != ACK)
{
// Write "7F" to start communicating with Bootloader
_serialPort.Write(sevenF, 0, 1);
Thread.Sleep(100);
// read ACK byte after parameters set and bootloader running
byte_read = _serialPort.ReadByte();
}
}
public void EraseFlashMemory(SerialPort _serialPort)
{
int byte_read = 0;
var ff = new byte[] { 0xFF };
Console.WriteLine("Erasing flash memory...");
Console.WriteLine("");
/* NOTE: the ERASE COMMAND is not supported by this device, use EXTENDED ERASE */
// Send 0x44 and 0xBB (extended erase memory command), see AN3155
var exeraseMem = new byte[] { 0x44 };
var bb = new byte[] { 0xBB };
_serialPort.Write(exeraseMem, 0, 1);
_serialPort.Write(bb, 0, 1);
// Receive ACK byte
byte_read = _serialPort.ReadByte();
if (byte_read == NACK)
{
//Console.WriteLine("NACK received for ERASE MEMORY start");
//Console.WriteLine("");
}
//// end sending EXTENDED ERASE COMMAND
//---------------------------------------
// Global erase (send 0xFFFF, and 0x00)
//---------------------------------------
//var globalErase = new byte[] { 0x00 };
//_serialPort.Write(ff, 0, 1);
//_serialPort.Write(ff, 0, 1);
//_serialPort.Write(globalErase, 0, 1);
// Erase all but the first page (16k)
// send number of pages to erase, msb first [11 pages, leaving page 0]
// *ALERT* send 10 pages (N) to erase 11, for some reason it erases N + 1, whatever...
var num_pages_msb = new byte[] { 0x00 };
var num_pages_lsb = new byte[] { 0x0A };
_serialPort.Write(num_pages_msb, 0, 1);
_serialPort.Write(num_pages_lsb, 0, 1);
// send page numbers, 2 bytes each, msb first
// PAGE 1
var page01_msb = new byte[] { 0x00 };
var page01_lsb = new byte[] { 0x01 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page01_lsb, 0, 1); // 1
// PAGE 2
var page02_lsb = new byte[] { 0x02 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page02_lsb, 0, 1); // 2
// PAGE 3
var page03_lsb = new byte[] { 0x03 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page03_lsb, 0, 1); // 3
// PAGE 4
var page04_lsb = new byte[] { 0x04 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page04_lsb, 0, 1); // 4
// PAGE 5
var page05_lsb = new byte[] { 0x05 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page05_lsb, 0, 1); // 5
// PAGE 6
var page06_lsb = new byte[] { 0x06 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page06_lsb, 0, 1); // 6
// PAGE 7
var page07_lsb = new byte[] { 0x07 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page07_lsb, 0, 1); // 7
// PAGE 8
var page08_lsb = new byte[] { 0x08 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page08_lsb, 0, 1); // 8
// PAGE 9
var page09_lsb = new byte[] { 0x09 };
_serialPort.Write(page01_msb, 0, 1); // 0
_serialPort.Write(page09_lsb, 0, 1); // 9
// PAGE 10
var page10_msb = new byte[] { 0x01 }; // 1
var page10_lsb = new byte[] { 0x00 }; // 0
_serialPort.Write(page10_msb, 0, 1);
_serialPort.Write(page10_lsb, 0, 1);
// PAGE 11
_serialPort.Write(page10_msb, 0, 1); // 1
_serialPort.Write(page01_lsb, 0, 1); // 1
// checksum = A
_serialPort.Write(num_pages_lsb, 0, 1);
// Receive ACK byte
byte_read = _serialPort.ReadByte();
bw.ReportProgress(20);
if (byte_read == NACK)
{
//Console.WriteLine("NACK received for ERASE MEMORY completed");
//Console.WriteLine("");
}
}
// -- end EXTENDED ERASE MEMORY --------------------------------------------------
public void WriteNewAppToFlash(SerialPort _serialPort)
{
// For testing
int blockCount = 0;
int byte_read = 0;
long checksum = 0;
var ff = new byte[] { 0xFF };
// ------------------------------------------------------------------------------
// -------- WRITE MEMORY --------------------------------------------------------
// ------------------------------------------------------------------------------
// for Address
int baseAddress = 0x08008000;
int offset = 0;
// for string from HEX file
string line;
string[] lineBuffer = new string[16];
int lineCount = 0;
int length;
int type;
int hexChecksum = 0;
bool sendAddress = true;
int counter = 0; // Counting the number of lines in the file
int byteCounter = 0; // Counting nmumber of bytes in the current block
// Create byte array with 256 bytes
byte[] buffer256 = new byte[256];
// Read the file and process one line at a time
System.IO.StreamReader file = new System.IO.StreamReader(path);
while ((line = file.ReadLine()) != null)
{
// Store line into a line buffer. This will allow reprocessing of all lines
// in a block if there is an error sending a block of 256 bytes below
if(line[8] == '0')
{
lineBuffer[lineCount++] = line;
}
// Send WRITE COMMAND and the next address every 256 bytes
if (sendAddress == true)
{
/*
-------------------------------------------------------------------------------------------------------
SEND WRITE COMMAND
-----------------------------------------------------------------------------------------------------*/
do
{
// Send WRITE command - 0x31 and 0xCE
var writeMem = new byte[] { 0x31 };
var ce = new byte[] { 0xCE };
_serialPort.Write(writeMem, 0, 1);
_serialPort.Write(ce, 0, 1);
// Receive ACK byte
byte_read = _serialPort.ReadByte();
} while (byte_read != ACK);
// -- end SEND 0x31 and 0xCE and wait for ACK -----------------------------------------
/*
-------------------------------------------------------------------------------------------------------
SEND CURRENT ADDRESS AND CHECKSUM TO FLASH MEMORY
-----------------------------------------------------------------------------------------------------*/
Byte[] currentAddr = BitConverter.GetBytes(baseAddress + offset);
// Increment offset by 0x100 (256 bytes)
offset = offset + 0x00000100;
// Reset Checksum and XOR address
checksum = 0;
foreach (byte b in currentAddr)
{
checksum ^= b;
}
Byte[] cksum = BitConverter.GetBytes(checksum);
// Send address, MSB first, LSB last
_serialPort.Write(currentAddr, 3, 1);
_serialPort.Write(currentAddr, 2, 1);
_serialPort.Write(currentAddr, 1, 1);
_serialPort.Write(currentAddr, 0, 1);
// Send checksum of address bytes
_serialPort.Write(cksum, 0, 1);
// Receive ACK byte
byte_read = _serialPort.ReadByte();
if (byte_read == NACK)
{
// Handle
}
// -- end addr or increment ---------------------------------------------------------
sendAddress = false;
// Send number of bytes, always 256, the last group will be padded with 0xFF
_serialPort.Write(ff, 0, 1);
} // end IF for WRITE COMMAND and ADDRESS
/* FIRST CHARACTER in HEX FILE
The colon indicates the start of a "record"
Remove colon from beginning of string */
line = line.Substring(1, line.Length - 1);
// Create byte array from string for whole line from HEX file
var bytes = GetBytesFromByteString(line).ToArray();
// Identify RECORD TYPE of HEX line [byte 4]
type = bytes[3];
/* Next TWO CHARACTERS 00-data 03-start segment address
in HEX FILE are 01-EOF 04-extended linear address
the record type: 02-extended segment address 05-start linear address */
// BLOCK WRITE TO MEMORY
if (type == 0)
{
// Length of line is stored at byte 0, in this case 0x10, or 16 bytes of data
length = bytes[0];
// Add data from current line to buffer of 256 bytes
for (int i = 0; i < length; i++)
{
// Stuff all bytes from line into buffer of 256 bytes
buffer256[byteCounter++] = bytes[4 + i];
// Add byte to checksum
hexChecksum ^= bytes[4 + i];
}
// When buffer is full, send block of 256 bytes and checksum, reset variables for next block
if (byteCounter >= 255)
{
// Convert checksum to a byte value
hexChecksum = hexChecksum^0xFF;
byte csByte = Convert.ToByte(hexChecksum);
Byte[] csByte_arr = BitConverter.GetBytes(csByte);
// Send byte array
_serialPort.Write(buffer256, 0, 256);
// For testing
// Console.WriteLine("block number [{0}]", ++blockCount);
//send checksum
_serialPort.Write(csByte_arr, 0, 1);
//Receive ACK byte
byte_read = _serialPort.ReadByte();
Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);
while (byte_read != ACK)
{
Array.Clear(buffer256, 0, buffer256.Length);
hexChecksum = 0;
lineCount = 0;
// reprocess the previous 16 lines stored in the line buffer
for (int j = 0; j < 16; j++)
{
line = lineBuffer[j];
line = line.Substring(1, line.Length - 1);
var bytesLocal = GetBytesFromByteString(line).ToArray();
length = bytesLocal[0];
for (int i = 0; i < length; i++)
{
buffer256[byteCounter++] = bytesLocal[4 + i];
hexChecksum ^= bytesLocal[4 + i];
}
}
// Convert checksum to a byte value
hexChecksum = hexChecksum^0xFF;
byte csByteLocal = Convert.ToByte(hexChecksum);
Byte[] csByte_arrLocal = BitConverter.GetBytes(csByteLocal);
// Send byte array
_serialPort.Write(buffer256, 0, 256);
//send checksum
_serialPort.Write(csByte_arrLocal, 0, 1);
//Receive ACK byte
byte_read = _serialPort.ReadByte();
Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);
}
// Clear buffer, reset byte count, clear checksum, set flag to send write cmd/send new addr
Array.Clear(buffer256, 0, buffer256.Length);
byteCounter = 0;
hexChecksum = 0;
lineCount = 0;
sendAddress = true;
}
} // end BLOCK WRITE TO MEMORY
else if (type == 1) // Marker for end of file
{
while (byteCounter != 0)
{
// Add 0xFF to the remaining bytes in this last block of 256
buffer256[byteCounter++] = 0xFF;
// Add byte to checksum
hexChecksum ^= 0xFF;
if (byteCounter >= 255)
{
byteCounter = 0;
// Convert checksum to a byte value
hexChecksum = hexChecksum^0xFF;
byte csByte = Convert.ToByte(hexChecksum);
Byte[] csByte_arr = BitConverter.GetBytes(csByte);
// Send byte array
_serialPort.Write(buffer256, 0, 256);
// For testing
// Console.WriteLine("block number [{0}]", ++blockCount);
//send checksum
_serialPort.Write(csByte_arr, 0, 1);
//Receive ACK byte
byte_read = _serialPort.ReadByte();
Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);
if (byte_read == NACK)
{
// ??
}
}
}
}
// end ELSE if TYPE == 1
counter++;
} // end WHILE loop for loading hex file
file.Close();
// For testing
// Console.WriteLine("File is closed.");
// System.Console.WriteLine("There were {0} lines.", counter);
// Console.WriteLine("");
// -- end WRITE MEMORY ------------------------------------------------------
} // end WriteNewAppToFlash
private void handleAppSerialError(IOException exc)
{
throw new NotImplementedException();
}
private void raiseAppSerialDataEvent(byte[] received)
{
throw new NotImplementedException();
}
public void JumpToNewApp(SerialPort _serialPort)
{
int byte_read = 0;
long checksum = 0;
var ff = new byte[] { 0xFF };
int baseAddress = 0x08000000;
// Jumps to flash memory 0x08000000, where the sector 0 code will perform a normal startup
// Send 0x21 (GO) and complement 0xDE
var go = new byte[] { 0x21 };
var de = new byte[] { 0xDE };
while (byte_read != 0x79)
{
_serialPort.Write(go, 0, 1);
_serialPort.Write(de, 0, 1);
// Receive ACK byte
byte_read = _serialPort.ReadByte();
if (byte_read == NACK)
{
//Console.WriteLine("NACK received for GO COMMAND start");
//Console.WriteLine("");
}
}
// -- end SEND GO COMMAND and wait for ACK -----------------------------------------
Byte[] startAddr = BitConverter.GetBytes(baseAddress);
// Reset Checksum and XOR address
checksum = 0;
foreach (byte b in startAddr)
{
checksum ^= b;
}
Byte[] cheksum = BitConverter.GetBytes(checksum);
// Send first byte (msb) of address
_serialPort.Write(startAddr, 3, 1);
// Send second byte of address
_serialPort.Write(startAddr, 2, 1);
// Send third byte of address
_serialPort.Write(startAddr, 1, 1);
// Send last byte (lsb) of address
_serialPort.Write(startAddr, 0, 1);
_serialPort.Write(cheksum, 0, 1);
Thread.Sleep(20);
// Receive ACK byte
byte_read = _serialPort.ReadByte();
} // end JUMPTONEWAPP
// Converts a string to a byte array
public static IEnumerable<byte> GetBytesFromByteString(string str)
{
for (int index = 0; index < str.Length; index += 2)
{
yield return Convert.ToByte(str.Substring(index, 2), 16);
}
}
protected void AssertOpenPort()
{
// if(!IsOpen)
// throw new InvalidOperationException("Serial Port is not open");
}
} // end public class FWupdater
请包括updater.updater()的源代码;''ReportProgress''必须从**那个**方法中调用。 – mjwills
你的代码清楚地表明'updater.updater()'必须在其他事情发生之前完成。您的当前代码永远不会在更新程序运行时更新进度,因为更新程序必须先完成才能更新进度。您的更新程序将不得不支持某些方法来显示它在过程中的位置,以便能够显示进度。 –
@mjwills - 试图从Updater更新ReportProgress,但没有更新已完成的百分比。是否应该使用相同的BackgroundWorker,或者应该是不同的实例。我不知道如何管理班级间的沟通。 – Gordon