none
請教各位如何讓Form2不斷的去讀取類別記憶體中的訊息? RRS feed

  • 問題

  • 在此請教各位先進,小弟目前做了2個介面 Form1(父介面)與Form2(子介面),另外還有一個類別(Class1)。

    但是目前兩者之間的傳遞資料方式不了解,因此麻煩各位前輩幫忙解惑一下。

    首先我先利用父介面呼叫類別中寫好的方法,並從Class中讀取出存在記憶體中的資料。但是在同時我也希望Form2的圖形介面能不斷的讀取 Form1中所讀到的資料。

    在此先說明一下我的code,重點部分我用粗體字標示起來。

    command.ranges 這個是寫在類別中計算並且存入記憶體的資料,在程式中能夠正確的運作。

    但是在Form2中卻無法去讀取command.ranges裡頭的資料,目前的問題應該是Form2一開始並沒有資料,所以無法正確的讀入訊息。但是有資料進來後卻又無法做即時的更新。目前只想的到用while迴圈去一直讀取,但是判斷式卻不知道該怎麼設計比較好。

    此外編譯上沒有問題,但是執行上卻有例外處理錯誤,以下貼出錯誤訊息,並且在下面Form2 code標示出來。
    類型 'System.NullReferenceException' 的未處理例外狀況發生於 Laser_URG_Maping_v00.exe

    其他資訊: 並未將物件參考設定為物件的執行個體

    目前在網路上查到的建議有幾種,publish、subscription、訂閱、發佈?

    小弟個人腦袋中只想的到用while迴圈來做,請教各位能不能給點意見。

    另外publish、subscription、訂閱、發佈,我查過了MSDN,不過卻不了解,如果各位前輩有例子的話,可否貼MSDN以外的一些範例呢?

    //***Form1***
    private void Form1_Load(object sender, EventArgs e)  //因為希望在父視窗起動時連同子視窗一同開啟,因此在load事件中先開起來
            {
                Form2 LamP = new Form2(); 
                LamP.Owner = this;
                LamP.MdiParent = this.MdiParent;
                LamP.Show();
            }

            private void button5_Click_1(object sender, EventArgs e)  // 呼叫類別並且下命令,然後取出其中的數值
            {
                char[] charArray = new char[2048];
                string[] strArray = new string[128];

                MyHardware.Hardware_v00 command = new MyHardware.Hardware_v00(serialPort1);
                Thread t = new Thread(new ParameterizedThreadStart(command.command));
                _DM_Gx1.LaserCommand cmd = new _DM_Gx1.LaserCommand(new byte[] { 0x47, 0x30, 0x30, 0x30, 0x37, 0x36, 0x38, 0x36, 0x34, 0x0a }, 0, 10);
                t.Start(cmd);
                t.Join();
                richTextBox1.Text = "";

                try
                {
                    richTextBox1.Text += "距離總數 : " + command.ranges.Count + "\n";

                    for (int j = 0; j < command.ranges.Count; j++)
                    {
                        richTextBox1.Text += String.Format("距離長度#{0} :", j);
                        richTextBox1.Text += command.ranges[j] + "cm";
                        richTextBox1.Text += '\n';
                    }
                }
                catch (Exception excp)
                {
                    MessageBox.Show(excp.ToString(), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }

    //***Form2***
            private void CreateGraph(ZedGraphControl zgc)
            {
                // get a reference to the GraphPane
                GraphPane myPane = zgc.GraphPane;

                // Set the Titles
                myPane.Title.Text = "雷射測距儀量測統計";
                myPane.XAxis.Title.Text = "角度值 (0~768)";
                myPane.YAxis.Title.Text = "距離 (cm)";

                double x, y1;
               
                MyHardware.Hardware_v00 command = new MyHardware.Hardware_v00(serialPort1);
                Thread t = new Thread(new ParameterizedThreadStart(command.command));
                PointPairList list2 = new PointPairList();

                try
                {
                        for (int i = 0; i <= command.ranges.Count; i++)  //上述例外處裡錯誤
                        {
                            x = i;
                            y1 = (double)command.ranges[i];
                        }

                    LineItem myCurve2 = myPane.AddCurve("距離長度", list2, Color.Blue, SymbolType.Circle);

                    zgc.AxisChange();
                }
               
                catch (Exception excp)
                {
                    MessageBox.Show(excp.ToString(), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }

    //*************************************************

    將目前要問的問題在整理一下:

    1.在兩個視窗介面中,要用什麼方法才能讓Form2(子視窗)不斷的去讀取class1類別中的資料?

    2.另外硬體每下一次命令(command),回傳過來的數值,是存在記憶體中嗎?如果是的話,在還沒釋放記憶體空間之前是不是可以一直重複呼叫?因為目前的做法是要讓Form1與Form2一起讀取Class1中,command.ranges這個陣列的資料。

    3.publish、subscription、訂閱、發佈,請教一下這些用法該如何用?有相關範例的話可以麻煩貼一下嗎?

    4.假如我利用了判斷式,在Form1啟動時,Form2讀不到資料將不做任何動作,我該怎麼寫比較好。例如...

    private void Form1_Load(object sender, EventArgs e)  //因為希望在父視窗起動時連同子視窗一同開啟,因此在load事件中先開起來
            {
                MyHardware.Hardware_v00 command = new MyHardware.Hardware_v00(serialPort1);
                if (command.ranges == null)
                {
               
                }else
                Form2 LamP = new Form2(); 
                LamP.Owner = this;
                LamP.MdiParent = this.MdiParent;
                LamP.Show();
            }
    if()裡面不需要做任何事情,讓他這樣做判斷就可以了嗎?雖然我自己做執行上沒甚麼問題,目前也還不懂怎麼抓出有沒有BUG。 @@

    //*************************************************

    整篇文章看起來有點雜,先感謝各位細心看完,摸了一陣子C#以後,老實說有些問題真的連怎麼問都不知道,在此也先謝謝各位前輩每次都不吝嗇的指教。

    如果有那邊描述不清楚的話我將會在寫的更詳細些。

    2009年7月23日 下午 03:45

解答

  • 蹂躪大的部落格有一篇[.NET兩個表單間的資料互通 ] , 應該對你有幫助
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Lolota Lee 2009年8月3日 上午 08:33
    2009年7月23日 下午 04:02
    版主
  • Demo 一下
    //單一物件,請改成你的資料型態
    public class Employee{
          private string employeeNo;
          private string employeeName;
          public string EmployeeNo{
              get{
                          return employeeNo;
                   }
              set{
                          employeeNo=value;
                    }
          }
              public string EmployeeName{
              get{
                          return employeeName;
                   }
              set{
                          employeeName=value;
                    }
          }
          public Employee(string employeeNo,string employeeName)
        {
              this.employeeNo=employeeNo;
              this.employeeName=employeeName;

         }
    }

    //具加入,刪除...集合式操作通知物件.
    public class EmployeeCollection:ObservableCollection<Employee>
    {
    }

    //秀員工資料UI
    public class ShowEmployeeViewForm:Form
    {
          private EmployeeCollection employees;
         
          public ShowEmployeeViewForm(EmployeeCollection employees)
        {
             this.employees=employees;
             this.employees.CollectionChanged+=new NotifyCollectionChangedEventHandler(OnUpdateEmployeeList); 
         }
         
         public void OnUpdateEmployeeList(object sender,NotifyCollectionChangedEventArgs args)
        {
               this.lbEmployee.ItemsSource=null;
               this.lbEmployee.ItemsSource=employees;
         }
    }

    public class MainForm:Form{
             private EmployeeCollection employees;
             private ShowEmployeeViewForm showEmployeeView;
             public EmployeeCollection Employees
            {
                 get{
                          if(this.employees==null)
                             this.employees=new EmployeeCollection();
                           return this.employees;
                      }
                 set{
                           this.employees=values;
                       }
             }
              
              public MainForm()
             {
                  this.showEmployeeView=new ShowEmployeeViewForm(this.Employees);
                  this.showEmployeeView.Show();
              }

              private void btnAdd_Click(object sender,EventArgs args)
             {
                   this.Employees.Add(new Employee("123","New Employee"));
              }
    }
    • 已標示為解答 Lolota Lee 2009年8月3日 上午 08:33
    2009年7月24日 上午 08:53

所有回覆

  • 蹂躪大的部落格有一篇[.NET兩個表單間的資料互通 ] , 應該對你有幫助
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    • 已標示為解答 Lolota Lee 2009年8月3日 上午 08:33
    2009年7月23日 下午 04:02
    版主
  • 這種問題已經討論了非常多次了.
    你要寫這種資料操作程式時要對DataBinding非常熟.你去看MSDN不管是WindowsForm或ASP.NET或WPF...都有一篇在說明這個.請把他看過再去寫.
    另外OO你也要懂.你要會寫Class.其中妳要熟Method跟Event 委派...在這一題,你FormA要執行 Class 裡的Method去對裡面資料作維護動作.FormB要去監聽Class裡的PropertyChanged 跟 CollectionChanged...事件.然後去刷新FormB的UI

    2009年7月24日 上午 12:27
  • 蹂躪大的部落格有一篇[.NET兩個表單間的資料互通 ] , 應該對你有幫助
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重

    您好,我想請教一下裡面的程式,關於下列範例中,Class Form1中的[Form2.MainForm = this;]。

    MainForm是在Form2中定義的變數名稱嗎?

    假如是的話,[Form2.MainForm = this;]是在Cass下呼叫?還是在於我要互傳資料的button事件下定義呢?

    另外,我在Form2中定義了MainForm卻無法叫。
    MainForm.Value = this.NumericUpDown1.Value;
    可能是我概念錯誤了,可以請大大指導一下嗎?


    C#

    Public Class Form1{
    ...
    //Form1透過Form2的Public成員把自身的物件參考傳入Form2
    Form2.MainForm = this;
    ...
    }

    Public Class Form2{
    ...
    Public Form1 MainForm;
    ...
    //'Form2透過Form1傳進的物件參考控制Form1
    MainForm.Value = this.NumericUpDown1.Value;
    ...
    }
    2009年7月24日 上午 07:37
  • 這部份看了一遍MSDN以後還是一知半解,網路上在找找相關教學。

    如果真的沒辦法也只好再去學校求助老師了,先在此感謝好說大大給的建議。

    目前先將你講的全部找過一次@@
    2009年7月24日 上午 07:44
  • 我說的已經是非常深了!你要看懂不是一天,二天的事了.
    而已你我樓上第二篇來看,你去查一下這個討論區,前幾篇有小朱示範的二個Form對船的範例就符合你的需求了.

    2009年7月24日 上午 08:00

  • 另外,我在Form2中定義了MainForm卻無法叫。
    MainForm.Value = this.NumericUpDown1.Value;
    可能是我概念錯誤了,可以請大大指導一下嗎?


          Public Form1 MainForm; <--這樣宣告MainForm
          MainForm.Value = this.NumericUpDown1.Value; <--要利用MainForm.Value屬性取值
          已知Form1 是繼承Form類別而來, 但是Form類別並沒有 Value屬性.
          所以在Class Form1裡要自行定義一個屬性叫Value.
       
    請關心自己的問題,不要問了就放空;這是對別人與自己的尊重
    2009年7月24日 上午 08:19
    版主
  • Demo 一下
    //單一物件,請改成你的資料型態
    public class Employee{
          private string employeeNo;
          private string employeeName;
          public string EmployeeNo{
              get{
                          return employeeNo;
                   }
              set{
                          employeeNo=value;
                    }
          }
              public string EmployeeName{
              get{
                          return employeeName;
                   }
              set{
                          employeeName=value;
                    }
          }
          public Employee(string employeeNo,string employeeName)
        {
              this.employeeNo=employeeNo;
              this.employeeName=employeeName;

         }
    }

    //具加入,刪除...集合式操作通知物件.
    public class EmployeeCollection:ObservableCollection<Employee>
    {
    }

    //秀員工資料UI
    public class ShowEmployeeViewForm:Form
    {
          private EmployeeCollection employees;
         
          public ShowEmployeeViewForm(EmployeeCollection employees)
        {
             this.employees=employees;
             this.employees.CollectionChanged+=new NotifyCollectionChangedEventHandler(OnUpdateEmployeeList); 
         }
         
         public void OnUpdateEmployeeList(object sender,NotifyCollectionChangedEventArgs args)
        {
               this.lbEmployee.ItemsSource=null;
               this.lbEmployee.ItemsSource=employees;
         }
    }

    public class MainForm:Form{
             private EmployeeCollection employees;
             private ShowEmployeeViewForm showEmployeeView;
             public EmployeeCollection Employees
            {
                 get{
                          if(this.employees==null)
                             this.employees=new EmployeeCollection();
                           return this.employees;
                      }
                 set{
                           this.employees=values;
                       }
             }
              
              public MainForm()
             {
                  this.showEmployeeView=new ShowEmployeeViewForm(this.Employees);
                  this.showEmployeeView.Show();
              }

              private void btnAdd_Click(object sender,EventArgs args)
             {
                   this.Employees.Add(new Employee("123","New Employee"));
              }
    }
    • 已標示為解答 Lolota Lee 2009年8月3日 上午 08:33
    2009年7月24日 上午 08:53
  • HI,

    先下載範例下來看一下

    直接看範例會比較清楚

    http://www.dotblogs.com.tw/larrynung/
    2009年7月24日 上午 08:54
  • 各位前輩不好意思,目前還在摸索中,請容許我慢一點選出最佳解答。
    2009年7月27日 上午 07:03
  • HI,

    先下載範例下來看一下

    直接看範例會比較清楚

    http://www.dotblogs.com.tw/larrynung/
    蹂躪前輩您好,最近看了您的範例之後,發現VB跟C#之間有些應用方式不同,能在此請教一下嗎?

    您在範例中建立的事件中

        Protected Sub OnSetValueToForm1(ByVal e As EventArgs)
            RaiseEvent SetValueToForm1(Me, e)
        End Sub
     
    RaiseEvent好像只有VB能使用,如果要改成C#的話,我該如何改呢??
    2009年7月31日 上午 09:09
  • Hi,

    請參考
    event (C# 參考)

    event 關鍵字用於在發行者 (Publisher) 類別中宣告事件。



    C# 程式設計手冊
    事件 (C# 程式設計手冊)

    http://www.dotblogs.com.tw/larrynung/
    2009年7月31日 上午 09:27