我一直在研究WinForms实用程序,该实用程序从文本文件中获取命令和/或数据,并根据此文件的内容通过串行传输或请求更多数据。这一切都很完美,但我正在努力研究如何让GUI给出一些反馈,说明事情正在发生。在当前结构中,主窗体加载,Load()
事件打开文本文件并处理其内容
tp = new TProcess();
tp.FileOpen();
TProcess和通过串口进行通信所涉及的所有其他类被收集到一个编译为DLL的子项目中。反过来,TProcess将创建我的SerialDevice对象的一个新实例(也在我的DLL中定义)并传递给我的数据,然后告诉它如何处理它,例如
//TProcess
if (File.Exists(filey))
try
{
StreamReader file = new StreamReader(@"filey");
List<clsStuff> stuffList = new List<clsStuff>();
while ((line = file.ReadLine()) != null)
{
//process and add to list
}
var SD = new SerialDevice();
SD.List = stuffList;
SD.Send();
file.Close();
}
catch (Exception e)
{
//Write Error File
}
}
我的SD类定义所有端口参数,发送第一个项目数据包并使用DataReceived事件从远程设备接收确认数据包,然后一次一个地从列表中发送项目,直到它完成并退出。 因此,我的问题(抱歉长篇大论)是我如何传递某种反馈(也许像每次收到数据包确认时收到的记录X之类的字符串),因为GUI线程没有创建我的SD,所以GUI正在发生例如,如果这是一个更紧凑的程序并且GUI线程已经调用SD我将使用委托和BeginInvoke但我不知道我怎么能在这里做,因为GUI对SD实例一无所知,同样SD对此一无所知GUI。我觉得这可以通过SynchronisationContext解决,但我不知道如何实现它。
public void Send()
{
if (!serialP.IsOpen)
{
PortOpen();
serialP.ReceivedBytesThreshold = 4;
}
serialP.Write(CurrentListItem, 0, 11);
}
private void serialP_DataEvent(object sender, SerialDataReceivedEventArgs e)// This triggers when the response is received
{
byte[] Ack = new byte[4];
serialP.Read(Ack, 0, 4);
//snip of course I check these 4 bytes etc here
CurrentListItem++;
//UPDATE THE GUI BUT HOW?
Send()!;//next
}
答案 0 :(得分:0)
向您的TProcess
班级添加您的用户界面可订阅的活动:
public event EventHandler DataRecieved;
然后在serialP_DataEvent
你可以,在适当的时候做:
if (DataRecieved != null)
{
DataRecieved(this,EventArgs.Empty);
}
然后您的用户界面可以订阅:
tp.DataRecieved += (o,e) => { // do something to the UI };
几点说明:
1)如果您使用通用EventHandler<T>
而不是EventHandler
,则可以在事件中传递信息。其中T
是您要发送的任何数据类
2)看起来FileOpen
是同步和阻止的,所以它会阻止你的UI更新。使其异步或至少使用Task.Run
3)如果你使它异步,那么你可能会遇到尝试从不是UI线程的线程更新UI的问题。您将需要使用Invoke
将UI更新推送回UI线程(您不会说这是WinForms还是WPF,但它们是相似的)。