2011-07-15 159 views
1

经过大量的研究,我仍然难倒了。我有一个连续读取数据的串口对象。我所能做的就是生成dataReceived事件,与端口通信,并将接收到的值输出到调试窗口。所以,我很确定这一切都在身体上运作。问题是当我尝试将串行端口输出传递给我的原始线程时出现错误。它说我不能有线程交叉讨论(或者是那种效果)。我一直在尝试使用backgroundWorker,但我不确定这是我想要的解决方案,加上我的新手技能有点超出我的头脑。我试图使用调用,但该方法似乎不可用。 (我可能是从错误的对象调用?)无论如何部分在下面。线程之间的串口通信

namespace Photometer 
{ 
    class csRadiometerILT1700 
    { 
     //manufacturer specs for baud rate, databits, and stop bits 
     static string portName="COM1"; 
     static int baudRate = 1200; 
     static int dataBits = 8; 
     //instantialize a serial port object for the Radiometer 
     private SerialPort RadiometerSerial = new SerialPort(portName, baudRate, Parity.None, dataBits, StopBits.One); 


     //constructor 
     //public csRadiometerILT1700(Form ParentForm, Chart outputChart) 
     public csRadiometerILT1700() 
     { 


      //two handshaking properties of the ILT1700. Handshaking is enabled and 
      //http://stackoverflow.com/questions/6277619/problem-reading-serial-port-c-net-2-0-to-get-weighing-machine-output 
      RadiometerSerial.Handshake= Handshake.RequestToSend; 
      RadiometerSerial.DtrEnable = true; 

      RadiometerSerial.DataReceived += new SerialDataReceivedEventHandler(RadiometerSerial_DataReceived); 

     } 

     public void openPort() 
     { 
      if (!RadiometerSerial.IsOpen) 
      { 
       RadiometerSerial.Open(); 
      } 

     } 
     public void closePort() 
     { 
      RadiometerSerial.Close(); 
     } 

     string RadiometerVoltageReadingString; 
     int RadiometerVoltageReadingInt; 
     private void RadiometerSerial_DataReceived(object sender, SerialDataReceivedEventArgs e) 
     { 
      //It's here that this.invoke()... cannot be called. 

      RadiometerVoltageReadingString= (RadiometerSerial.ReadExisting().ToString()); //y-value 
      Debug.Print(RadiometerVoltageReadingString.ToString()); 

      makeRadioReadingDouble(RadiometerVoltageReadingString); 

     } 

     private void makeRadioReadingDouble(string inputVoltageString) 
     { 

      List<double> outputVoltageDouble=new List<double>(2); 


      if (!(inputVoltageString == "\r\n" || inputVoltageString == "")) 
      { 
       string[] voltageValAndExpo = inputVoltageString.Split(new string[] { "e", "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 

       for (int inCounter = 0; inCounter < voltageValAndExpo.Count(); inCounter=inCounter+2) 
       { 
        double voltageVal = Convert.ToDouble(voltageValAndExpo[inCounter]); 
        double voltageExpo = Convert.ToDouble(voltageValAndExpo[inCounter + 1]); 

        outputVoltageDouble.Add(Math.Pow(voltageVal, voltageExpo)); 
       } 
      } 
     } 

    } 
} 

这是当我形成任何有识之士的赞赏码

  csRadiometerILT1700 Radiometer; 

      ... 

      Radiometer = new csRadiometerILT1700(); 
      Radiometer.openPort(); 

加载所有调用。

编辑: 我改变了我的csRadiometerILT1700构造函数

public csRadiometerILT1700(Form inputForm) 
    { 

     //inputForm.Invoke(
     //two handshaking properties of the ILT1700. Handshaking is enabled and 
     //http://stackoverflow.com/questions/6277619/problem-reading-serial-port-c-net-2-0-to-get-weighing-machine-output 
     RadiometerSerial.Handshake= Handshake.RequestToSend; 
     RadiometerSerial.DtrEnable = true; 

     RadiometerSerial.DataReceived += new SerialDataReceivedEventHandler(RadiometerSerial_DataReceived); 
     inputForm.Invoke(DataReceived); 
    } 

,并在csRadiometerILT1700类中声明

public event Delegate DataReceived; 

。但是这给了我“数据接收必须是委托类型”的错误。我现在如何解决这个问题?我在正确的轨道上吗?

+0

请勿从ctor中调用。以下是设置事件的链接:http://stackoverflow.com/questions/2448487/how-to-dispatch-events-in-c/2448530#2448530 –

+0

当收到有意义的数据时,您的课程应该提高其事件。将它打包成一个EventArgs派生类。表单订阅(+ =)并在其处理程序中调用。 –

回答

2
  1. 您的RadiometerILT1700类需要event来报告它收到(和处理)的数据。
  2. 您的表单订阅了该事件
  3. Forms事件处理程序使用this.Invoke()来克服跨线程问题。
+0

1.这是否会在DataReceived事件中触发?一旦我完成处理X数量的串行数据,我会标记事件? 2.如何从通话表单订阅? 3.这是否意味着我把“订阅”放在Invoke()中? – Brad

+0

1)是的,2)与'+ ='一样,与其他事件一样,3)不,您调用表单订阅的Form方法。到另一个或相同的方法。 –

+0

对不起,我还是输了。我可能需要多一点手牌。你能用更多的词来描述与2)相关的行动吗? – Brad

0

无论何时您尝试从其他线程发布到主线程,您都会遇到此错误。您需要对要从不是主窗体线程的线程调用的控件使用委托和调用。

0

假设误差实际上是:从比它 创建的线程以外的线程访问

控制控制名称。

问题是你不能从另一个线程影响你的GUI。您需要使用invoke表单或控件来传递控件,以便修改它。您应该能够与大多数其他元素交互,但不能与表单交互。

0

你不应该在那里调用this.Invoke,你这样做的方式就像试图将你自己的线程与你自己的线程同步到UI。你应该叫formhandle.Invoke,或窗体类寄存器内的事件,然后你可以使用this.invoke

1

Invoke是一个DelegateFormControl的方法,因为csRadiometerILT1700是没有这些是不是继承了其调用实行这些类。

您将需要提出另一个事件的csRadiometerILT1700呼叫者和hadle上优桂某处(任何跨线程问题一起)。另外,你可以提供csRadiometerILT1700与委托它可以使用回调,有点像手卷事件。

一旦你的表单中有数据,你可以使用Control.InokeRequired来检测跨线程情况,并且使用Control.Invoke来进行跨线程调用。

+0

我想我对委托语法感到困惑。呼叫形式中的哪些部分以及哪些部分在事件处理的类中进行? – Brad

+0

'delegate'是函数签名的定义。 'Delegate'或'MultiCastDelegate'是代表'delegate'实例的类。 一个'event'是一个指定'委托'的'MulticastDelegate',带有一个用于“引发”或“调用”调用的快捷方式。 – Jodrell

+0

'delegate'可以在任何地方声明,'event'应该放在想要提升它的类上。匹配并用于订阅事件“MulticastDelegate”的函数应该位于想要处理事件的类上。 – Jodrell