我正在尝试修复我的Winforms应用程序中的问题,而GUI往往会锁定。
当前解决方案: 编写应用程序以从串行端口读取并写入GUI中的富文本框。 现在,响应可以是单个响应,也可以是基于输入的高速连续流式传输。
截至目前,我正在使用内容更新文本框,当我从设备接收内容时,即。使用从串行端口接收数据时触发的事件处理程序。
后台工作人员是问题的唯一解决方案吗?如果是,我如何重构我的解决方案以适应这种变化?(我知道后台工作者无法访问GUI)。 如果没有,有没有更好的解决方案?
代码编辑: 这是一般代码流程
//Function triggered when data received from serial port
private void DataReceived(object sender, EventArgs e)
{
while (serialPort1.BytesToRead > 0 && serialPort1.IsOpen)
{
//calls to several processing functions
//which then call a function writetoTextBox and pass the data to write
}
}
//write to textbox
void writeToTextBox(inputdata)
{
// write to textbox.
//If user has asked to write to file. Open a file dialog to get file name and write to it
// as well. As of now when the data rate is high, this part doesnt get the time to respond
//as the GUI locks up the thread
}
免责声明:我对winforms和C#都比较陌生。所以任何建议都将不胜感激!
答案 0 :(得分:3)
您可以在此处使用多种方法:
BackroundWorker
(您建议的)Task
对象和async/await
:Asynchronous Programming with Async and Await - MSDN Thread
:Thread Class - MSDN 我建议使用async/await
方法,因为MS已经完成了确保所有内容保持同步的艰苦工作,但您可以根据应用决定您想要的内容。
要确保您可以访问UI线程,您必须使用Invoke
方法:Updating the GUI from another thread - SO
滚动自己的Thread
的示例如下:
为避免锁定用户界面,您可以执行以下操作:
private delegate void writeToTextBoxDelegate(List a, List b);
private async void DataReceived(object sender, EventArgs e)
{
while (serialPort1.BytesToRead > 0 && serialPort1.IsOpen)
{
await Task.Factory.StartNew(() =>
{
// Do whatever work you want to do here.
// When you're all done, call the following line.
textBox.Invoke(
new writeToTextBoxDelegate(writeToTextBox),
new object[] { a, b }
);
});
}
}
如果你在while
循环中所做的额外工作不重要,你可能想要移动
await Task.Factory.StartNew(() => { });
到while
循环之外。目标是不要过分严重地绑定Task
,因为允许运行Task
的线程数量有限。
调用Invoke
的另一种方法如下:
private delegate void writeToTextBoxDelegate(List a, List b);
private void writeToTextBox(List a, List b)
{
if (textBox.InvokeRequired)
{
textBox.Invoke(new writeToTextBoxDelegate(writeToTextBox),
new object[] { a, b });
return;
}
// Your custom write-to-textbox code here.
}
然后您可以从任何地方简单地调用writeToTextBox
,它将处理调用本身。
答案 1 :(得分:0)
为避免重新编码您的所有项目,您可以尝试使用Application.DoEvents()
。
void writeToTextBox(inputdata)
{
/*your code */
Application.DoEvents();
}
您可以看到there方法的说明和一些示例。希望这有帮助!