Прежде всего, дубликат является дубликатом.Вы не можете изменить пользовательский интерфейс из другого потока.До .NET 4.5 люди использовали Invoke
или BeginInvoke
на элементе управления , чтобы маршалировать делегат в потоке пользовательского интерфейса и запускать его там.Код вопроса, тем не менее, вызывает Invoke()
сам по себе, фактически выполняя делегат в потоке, в котором он в данный момент находится.
Короче говоря:
Invoke(new MethodInvoker(delegate () { listBox1.Items.Add(fc1); listBox1.Items.Add(StartAddress1); listBox1.Items.Add(NumOfPoints1); }));
По сути то же самое, что и эточто касается потоков:
listBox1.Items.Add(fc1); listBox1.Items.Add(StartAddress1); listBox1.Items.Add(NumOfPoints1);
В .NET 4.5 и более поздних версиях вы можете использовать Progress для отчета о прогрессе из любого потока или задачи, как показано в Включение выполнения и отмены в API-интерфейсах Async ,Учитывая, что самая ранняя поддерживаемая версия .NET - это 4.5.2, вы можете предположить, что класс доступен везде.
Используя интерфейс Progress<T>
и IProgress<T>
, вы можете отделить .событие из пользовательского интерфейса, что означает, что вы можете обрабатывать данные любым способом, даже в разных формах.Вы можете переместить класс Modbus в другой класс или библиотеку, чтобы отделить его от пользовательского интерфейса.
В простейшем случае вы можете создать экземпляр класса Progress<T>
в конструкторе вашей формы и вызвать его через IProgress<T>
интерфейс из обработчика событий, например:
public class ModbusData
{
public byte Fc {get; set;}
public short StartAddress {get; set;}
public short NumOfPoints {get; set;}
}
public class MyForm : ...
{
IProgress<ModbusData> _modbusProgress;
public MyForm()
{
__modbusProgress=new Progress<ModbusData>(ReportProgress);
}
public void ReportProgress(ModbusData data)
{
listBox1.Items.Add(data.fc1.ToString());
listBox1.Items.Add(dta.StartAddress1.ToString());
listBox1.Items.Add(data.NumOfPoints1.ToString());
}
и отчет о ходе выполнения события, независимо от того, на каком потоке он возник:
public void Modbus_Request_Event(object sender, ModbusSlaveRequestEventArgs e)
{
//disassemble packet from master
byte fc = e.Message.FunctionCode;
byte[] data = e.Message.MessageFrame;
byte[] byteStartAddress = new byte[] { data[3], data[2] };
byte[] byteNum = new byte[] { data[5], data[4] };
short StartAddress = BitConverter.ToInt16(byteStartAddress, 0);
short NumOfPoint = BitConverter.ToInt16(byteNum, 0);
var modData = new ModbusData {
Fc = fc,
StartAddress = StartAddress,
NumOfPoints = NumOfPoint
};
_progress.Report(modData);
}
Если вы решили переместить классы Modbusдругому классу все, что вам нужно сделать, это передать им экземпляр IProgress<ModbusData>
, прежде чем вы начнете его использовать.
Например:
class MyModbusController
{
IProgress<ModbusData> _modbusProgress;
public MyModbusController(IProgress<ModbusData> progress)
{
_modbusProgress=progress;
}
public void Modbus_Request_Event(...)
}