2013-05-01 3 views
0

У меня есть приложение, в котором я посылаю инструкцию на микро через последовательный порт ПК нажатием кнопки. Затем микропоток передает данные, которые запускают обработчик обработанных данных. Это захватывается в строку.Заполнение списка после запуска потока последовательного порта

На данный момент я хочу использовать данные строки и заполнить свой список. Я могу сделать это, используя invoke, делегировать, потому что я все еще в потоке данных.

Можно ли каким-либо образом вызвать обработчик событий или простую процедуру, чтобы сделать это после выхода потока, так что мне не нужно использовать invoke, delegate? Строение подпрограмм работает нормально, если оно запускается кнопкой, но я бы хотел, чтобы он был запрограммирован для выполнения задачи.

Надеюсь, что это достаточно ясно, это мой первый пост.

Edit: Вот некоторые примеры кода -

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 

    //use 28591 or("ISO-8859-1") to cover all hex bytes from 0 - 255 
    serialPort1.Encoding = Encoding.GetEncoding(28591); 

    //wait for download to complete by monitoring cts line 
    if (HoldData == true) 
    { 
     while (serialPort1.CtsHolding == true) ; 
     HoldData = false; 
    } 

    else 
     Thread.Sleep(50); 

    string text = serialPort1.ReadExisting(); 

    switch (text[0]) 
    { 
     case '?': MemLabelUpdate(); break; 
     case '>': WriteConfig(text); break; 
     case '=': SealTest(text); break; 
     case '<': CurrentNumber(text); break; 

     default: DataDownload(text); break; 

    } 
} 

Первый байт строки текста является идентификатором, как к тому, что пришел в это, в свою очередь, вызывает функцию, которая заполнит Lables на главном. формы с использованием метода делегирования invoke в качестве его запуска в потоке, полученном данными. По умолчанию вызов функции загрузки данных проходит текст и сортирует его, поскольку это масса событий. Затем результаты передаются в поле списка в соответствующие столбцы. Я хочу уйти от использования метода делегирования invoke. Мне нужно выйти из port_datareceived потока, чтобы сделать это, и после выхода введите мою функцию, чтобы просто обновить список, как показано ниже. Как я могу запускать этот вид события программно.

private void btnDisplayData_Click(object sender, EventArgs e) 
{ 
    int SectionStart = 10; 
    int SectionEnd = 8; 
    listView1.Items.Clear(); 
    listView1.View = View.Details; 
    listView1.GridLines = true; 

    //Add columns to listview 
    listView1.Columns.Add("Event", 80, HorizontalAlignment.Center); 
    listView1.Columns.Add("Time", 80, HorizontalAlignment.Center); 
    listView1.Columns.Add("Date", 80, HorizontalAlignment.Center); 

    //Print results to listview box 
    ListViewItem ListItem; 
    for (int i = 0; i < 10; i++) 
    { 
     ListItem = listView1.Items.Add(DownloadedData.Substring(SectionStart,  SectionEnd)); 
     SectionStart += 8; 
     ListItem.SubItems.Add(DownloadedData.Substring(SectionStart, SectionEnd)); 
     SectionStart += 8; 
     ListItem.SubItems.Add(DownloadedData.Substring(SectionStart, SectionEnd)); 
     SectionStart += 8; 
    } 

    foreach (ColumnHeader column in listView1.Columns) 
    { 
     column.Width = -2; 
    } 

} 
+0

Необходимо выяснить вопрос: какие темы вы используете, используете ли вы класс C# SerialPort, в каком потоке вы создаете объект SerialPort. – Ryan

+0

Покажите нам соответствующий код и немного объясните, как вы хотите, чтобы он работал по-другому. Трудно сказать, что вы действительно просите здесь. –

ответ

0

Похоже, что события вы действительно интересует PinChange. Поэтому обработайте это, проверьте CTS, а затем используйте BeginInvoke, чтобы отправить сообщение обратно в поток пользовательского интерфейса, который может очистить буфер последовательного порта (без ожидания), проанализировать данные и обновить элементы управления.


В качестве дополнительной записки DataReceived события на самом деле бесполезно на Microsoft предоставляемого System.IO.Ports.SerialPort класса. Если вы хотите что-то сделать с данными, как только оно поступит, используйте BeginRead с обратным вызовом.

0

Вы по-прежнему не задавали никаких подробностей о проблеме с резьбой. Создан ли SerialPort в потоке пользовательского интерфейса, рабочий поток или BackgroundWorker? SynchronizationContext важен, и если SerialPort создается в другом потоке, тогда вам нужно использовать какой-то механизм для вызова или подбора данных обратно в поток пользовательского интерфейса для отображения.

Самым простым решением может быть только для вызова метода DownloadData (при условии, что метод обновляет интерфейс или вызывает другой метод для обновления пользовательского интерфейса):

 switch (text[0]) 
     { 
      case '?': MemLabelUpdate(); break; 
      case '>': WriteConfig(text); break; 
      case '=': SealTest(text); break; 
      case '<': CurrentNumber(text); break; 

      default: 
       if (InvokeRequired) 
        Invoke((MethodInvoker)delegate { DataDownload(text); }); 
       else 
        DataDownload(text); 
       break; 
     } 

Другой метод будет определять собственные события для полученных данных. YouOne может определить событие для одного или всех случаев.Вам может потребоваться определить событие для кода, который будет иметь доступ к пользовательскому интерфейсу, но может быть хорошей идеей добавить события для всех случаев, чтобы вы могли лучше компоновать протокол и перевести серийный код в отдельный класс:

// Create an EventArgs based class for the data 
public class DataDownloadEventArgs : EventArgs 
{ 
    public string Data { get; set; } 

    public DataDownloadEventArgs(string data) 
    { 
     Data = data; 
    } 
} 

public partial class Form1 : Form 
{ 

    // Event handler when data is downloaded 
    public event EventHandler<DataDownloadEventArgs> DataDownloaded; 

    // Virtual method to raise event to observers 
    protected virtual void OnDataDownloaded(DataDownloadEventArgs e) 
    { 
     var handler = DataDownloaded; 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    // Form constructor 
    public Form1() 
    { 
     InitializeComponent(); 
     // Add handler for the download event 
     DataDownloaded += new EventHandler<DataDownloadEventArgs>(DisplayData); 
    } 

    // Serial port receive event 
    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     // snip... 
     switch (text[0]) 
     { 
      case '?': MemLabelUpdate(); break; 
      case '>': WriteConfig(text); break; 
      case '=': SealTest(text); break; 
      case '<': CurrentNumber(text); break; 

      default: 
       DataDownload(text); 
       OnDataDownloaded(new DataDownloadEventArgs(text)); 
       break; 

     } 
     // snip... 
    } 

    // Change btnDisplayData_Click to the following: 
    private void DisplayData(object sender, DataDownloadEventArgs e) 
    { 
     // insert remaining code from btnDisplayData_Click 
    } 
} 

Если вы все еще возникают проблемы с нитью UI и событий, вы можете использовать расширение, чтобы поднять событие в поток пользовательского интерфейса, как this. Вот статья, которая может помочь, Cross-Thread Events.

Смежные вопросы