Как передать или сделать открытые переменные или поля доступными для Tthread? - PullRequest
0 голосов
/ 12 июля 2011

Я пишу и собираю программное обеспечение для Mono с использованием Delphi Prism. Итак, я решил, что моя последовательная связь будет обрабатываться потоком. Поскольку глобальные переменные строго запрещены, если вы не включите опцию глобальной переменной для проекта, я решил следовать соглашению с Delphi Prism. Итак, как вы можете передать или сделать общедоступные переменные или поля доступными для потока?

Вот мой тестовый код mainform:

MainForm = partial class(System.Windows.Forms.Form)

  private
    method SignalBtn_Click(sender: System.Object; e: System.EventArgs);
    method CommBtn_Click(sender: System.Object; e: System.EventArgs);
    method button1_Click(sender: System.Object; e: System.EventArgs);
    method button2_Click(sender: System.Object; e: System.EventArgs);
    method button4_Click(sender: System.Object; e: System.EventArgs);
    method button5_Click(sender: System.Object; e: System.EventArgs);
    method MainForm_Load(sender: System.Object; e: System.EventArgs); 
    method ShutdownBtn_Click(sender: System.Object; e: System.EventArgs);
    method MySerialData(sender: System.Object; e:SerialDataReceivedEventArgs);
    method LoginBtn_Click(sender: System.Object; e: System.EventArgs);
  protected
    method Dispose(disposing: Boolean); override;
  public
    RX:Array[0..5] of byte;
    TX:Array[0..6] of byte;
    serialPort1:System.IO.Ports.SerialPort;
    thr:Thread;
    stoploop:Boolean;
    mcommand:Byte;
    thechannel:Integer;
    constructor;
    method FillTable;
  end;

Вот тема для последовательной связи:

  ThreadComm = class(MainForm)
  public
    class procedure mythread; static;
  end;

Вот как работает ThreadComm:

class procedure ThreadComm.mythread;
begin
    while true do
    begin
        TX[0]:=$FF;
        TX[1]:=$01;
        TX[2]:=$01;
        TX[3]:=$04;
        TX[4]:=$A2;
        TX[5]:=(TX[2] xor TX[3] xor TX[4]);

        SerialPort1.Write(TX,0,6);
        while SerialPort1.BytesToWrite>0 do;
        Thread.Sleep(100);

        if (stoploop) then
            break;
    end;
end;

Каждый раз, когда я компилирую код, он выдает примерно 30 похожих сообщений об ошибках, в которых указано следующее:

Невозможно вызвать элемент экземпляра "SerialPort1" без ссылки на экземпляр

Я знаю, что означает ошибка, но единственный способ ее исправить - создать экземпляр mainform. Если вы сделаете это, то это не будет тот же экземпляр, что и экземпляр основной программы. Если это так, то вам придется создавать новый экземпляр mainform все время, когда вам нужен доступ к его полям или публичным переменным. Верно?

class method Program.Main(args: array of string);
begin
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
  Application.ThreadException += OnThreadException;
  **using lMainForm := new MainForm do
    Application.Run(lMainForm);**
end;

Я хочу использовать все переменные, которые находятся в потоке, и они находятся в публичной области mainform.

Спасибо

Ответы [ 2 ]

1 голос
/ 12 июля 2011

Ваша процедура потока (class procedure mythread; static;) выглядит как "статическая" или "класс", в то время как поля, к которым вы хотите получить доступ, являются обычными полями MainForm instance . Это не может работать, потому что есть один-единственный procedure mythread, но может быть несколько экземпляров MainForm. Хотя на практике, вероятно, будет только один экземпляр MainForm, компилятор этого не знает.

Вы должны начать с удаления префикса class и суффикса static из этой процедуры, чтобы сделать ее обычной процедурой экземпляра, которая может читать поля экземпляра. Даже этого будет недостаточно, потому что вы получили из своей MainForm, и я предполагаю, что вы создаете новый экземпляр ThreadCom и запускаете поток: как только вы сделаете метод обычным методом экземпляра, код будет компилировать, но результат не будет ожидаемым, потому что вы будете получать доступ к элементам другого экземпляра MainForm.

Решения:

  • Сделайте процедуру mythread методом экземпляра вашего MainForm. Он получит доступ ко всем обязательным полям и получит доступ к ним из соответствующего экземпляра!
  • Следуйте совету Роба: создайте новый класс, , а не , полученный из MainForm, передайте ему экземпляр MainForm в конструкторе, то есть в процедуре потока. Вам (опять же) нужно избегать статических / классовых полей и процедур, поскольку они не могут быть связаны с одним экземпляром MainForm.
1 голос
/ 12 июля 2011

Передайте вещи, которые нужны вашему потоку как параметры своему конструктору.Храните ссылки на эти объекты как поля в вашем классе потока.Используйте их во время работы вашего потока.

И не делайте ваш класс потока потомком вашей основной формы.Это бессмысленно.Если вашему потоку нужен доступ ко всей форме, передайте ссылку MainForm в конструктор потока.Но если все ваши потоки нуждаются в объекте последовательного порта, то просто передайте это, а не всю форму.

Не создавайте дополнительные экземпляры MainForm.Это создаст больше форм;он не даст вам доступа к значениям полей вашей реальной главной формы.

...