如何快速跨线程操作? [英] how to fast cross thread operations ?

查看:134
本文介绍了如何快速跨线程操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,首先请原谅我的英语,我会尝试成为最可靠的。



我正在开发一个Arduino接口,其目的是为了在文本框中显示有关串口的信息。



问题是当我将信息打印到文本框中进行调用时,表单变慢或崩溃。



我正在使用后台工作人员从串口读取。



  private   void  backgroundWorker1_DoWork( object  sender ,DoWorkEventArgs e)
{
while (serialPort1.IsOpen)
{
textBox1.Invoke((MethodInvoker)( ()= > textBox1.Text = serialPort1.ReadLine()));
}
}





如何在不使应用程序变慢的情况下打印serialPort1.ReadLine()的结果?



谢谢

西蒙娜。

解决方案

我明白了:你做过最糟糕的UI滥用和调用我见过。你需要做相反的事情:在服务器线程中进行所有串行通信,使用Invoke在UI中显示数据(或用UI做任何事情)。



你不能打电话任何与非UI线程的UI相关的内容。相反,您需要使用 Invoke System.Windows.Threading的方法。 Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表单)。



您将在我过去的答案中找到有关其工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke() [ ^ ],

使用Treeview扫描仪和MD5的问题 [ ^ ]。



另请参阅有关线程的更多参考资料:

如何让keydown事件在不同的操作上运行vb.net中的线程 [ ^ ],

在启用禁用+多线程后控制事件未触发 [ ^ ]。



-SA


你可以尝试这种方法,而不是使用 SerialPort 类的事件。



然后没有必要循环工作。



将此方法添加到您的主class

  public  委托  void  UpdateTextBoxDelegate( string 文字); 
private void UpdateTextBox( string text)
{
if (textBox1.InvokeRequired)
{
textBox1.BeginInvoke( new UpdateTextBoxDelegate(UpdateTextBox),text);
}
else
{
textBox1.Text = text;
}
}





将此活动添加到您的主班。

< pre lang =c#> this .serialPort1.DataReceived + = new System.IO.Ports.SerialDataReceivedEventHandler ( this .serialPort1_DataReceived);





在活动中添加代码在文本框中设置值。

  private   void  serialPort1_DataReceived( object  sender,System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (e.EventType == System.IO.Ports.SerialData.Chars)
{
UpdateTextBox(serialPort1.ReadLine());

UpdateTextBox(serialPort1.ReadExisting());
}
}


即使串口操作相当简单,并且在单独的线程中使用串行通信也是非常合理的,问题根本不明确。请看我对这个问题的评论。



回答问题的标题:它没有多大意义,因为你所有的串口传输都是(比喻)说)比任何可想想的线程间通信慢得多。如果通过打印意味着使用打印机,它也会无限慢。 :-)



因此,如果您对软件的性能有任何疑虑,请解释您的特定问题。我认为没有理由担心它。如果你真的设法让你的申请太慢,请提供更多信息。



-SA


hello everyone, first excuse my english, i'll try to be the most comprensible I can.

I'm developing an Arduino interface whose purpose is to show in a textbox the information abouth serial port.

the matter is that when I print the information into the text box traught the invoke, the form became slow or crash.

I'm reading from serial port using a background worker.

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (serialPort1.IsOpen)
            {
                textBox1.Invoke((MethodInvoker)(() => textBox1.Text = serialPort1.ReadLine()));
            }
        }



how can I print the result of serialPort1.ReadLine() without making the application slow ?

thanks
Simone.

解决方案

I got it: you have done the worst abuse of UI and Invoke I ever saw. You need to do the opposite: do all serial communication in the server thread, use Invoke to show data in UI (or doing anything with UI).

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA


You can try this approach instead using the events of the SerialPort class.

Then there is no need to work in a loop.

Add this method to your main class

public delegate void UpdateTextBoxDelegate(string text);
private void UpdateTextBox(string text)
{
  if (textBox1.InvokeRequired)
  {
    textBox1.BeginInvoke(new UpdateTextBoxDelegate(UpdateTextBox), text);
  }
  else
  {
    textBox1.Text = text;
  }
}



Add this event to your main class.

this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);



Inside the event you add the code to set the value in the text box.

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    if (e.EventType == System.IO.Ports.SerialData.Chars)
    {
        UpdateTextBox(serialPort1.ReadLine());
        or
        UpdateTextBox(serialPort1.ReadExisting());
    }
}


Even though the serial port operation is fairly simple and using serial communication in a separate thread is quite reasonable, the question is not clear at all. Please see my comment to the question.

Answering just to the header of the question: it does not make much sense, just because all you serial port transport is (figuratively speaking) infinitely slower than any thinkable inter-thread communications. And if by "printing" you mean using a printer, it is also infinitely slower. :-)

So, if you have any concerns of the performance of the software, please explain your particular concerns. I don't think there is a reason to worry about it. If you really managed to make your application too slow, please provide more information.

—SA


这篇关于如何快速跨线程操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆