从C#中持续运行的线程中提取数据

时间:2016-10-30 18:28:09

标签: c# multithreading datagridview udpclient

我正在开发一个持续监听UDP端口514(syslog)上的数据包的项目。收到数据包后,我需要解析该消息,以便它可以在我的主窗体上显示在DataGridView控件中。

我有它所以用新消息更新DataGridView,但我可以从我的防火墙获取超过100条syslog消息,因此我想搜索我的dataGrid,看看消息是否已经存在,然后更新“点击计数“列而不是为重复的消息创建新行。

问题是我无法弄清楚如何在foreach循环中调用我的DataGridView。我没有从线程返回值,我正在处理数据,因此我需要从UI线程调用DataGridView控件。

到目前为止我的代码:

private async void Form1_Load(object sender, EventArgs e)
{
    var udpCap = await Task.Run(() => captureSyslog());
}
public async Task<string> captureSyslog()
{
    var listener = new UdpClient(514, AddressFamily.InterNetwork);
    var ep = default(IPEndPoint);
    while (true)
    {
        try
        {                    
            var data = listener.Receive(ref ep);
            string incomingSyslog = Encoding.ASCII.GetString(data);
            outputMessage(incomingSyslog);
        }
        catch (Exception ex2)
        {
            outputMessage(ex2.ToString());
        }
    }
}
private void outputMessage(string txt)
{
    string[] chopped = txt.Split(',');
    string descrip = chopped[32];
    string severity = chopped[34];
    string paloalto = chopped[59];
    int rowIndex = -1;
    foreach (DataGridViewRow row in syslogOutput.Rows)
    {
        try
        {
            if (row.Cells[2].Value.ToString().Equals(descrip) | row.Cells[1].Value.ToString().Equals(paloalto))
            {
                //Code to update DataGridView
            }
        }
        catch (Exception ex3){ debugLabel1.Invoke(new Action(() => debugLabel1.Text = ex3.ToString()));}
    }
    if (syslogOutput.InvokeRequired)
    {
        syslogOutput.Invoke(new Action(() => syslogOutput.Rows.Add("1", chopped[59], chopped[34], chopped[32])));
    }
}

当代码像这样运行时,我得到一个“System.NullReferenceException:对象引用未设置为对象的实例”,这是有道理的,因为“syslogOuput”​​DataGridControl在调用它的线程中不存在。但是,“syslogOutput.Invoke”行更进一步,因为它是从主UI线程中提取的。

此外,我可以使用Form1_load方法中的udpCap var来更新我的数据网格,但是当我这样做时,我只得到一条消息并且Task.Run线程退出。

所以我想我的问题可以用两种方式表达:

  1. 如何在foreach循环中调用控件?
  2. 和/或

    1. 如何在不结束返回值的任务的情况下从任务获取返回值?
    2. 更新 我转储了Task并使用BackgroundWorker功能捕获syslog消息。我在ProgressChanged方法中滥用了UserState来传递syslog字符串,因此我可以解析,然后在UI线程中本地显示它到我的DataGridView。据我所知,如果没有取消和/或ReportProgress方法永远不会收到“100”表示该进程100%完成,BackgroundWorker线程将永远运行。

      新代码:

      namespace ASA_SyslogCapture
      {
          public partial class Form1 : Form
          {
              BackgroundWorker bgWorker;
              public Form1()
              {
                  InitializeComponent();
                  bgWorker = new BackgroundWorker();
                  bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
                  bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
                  bgWorker.WorkerReportsProgress = true;
              }
              private async void Form1_Load(object sender, EventArgs e)
              {
                  bgWorker.RunWorkerAsync();
              }
              void bgWorker_DoWork(object sender, DoWorkEventArgs e)
              {
                  //put udp code here
                  var listener = new UdpClient(514, AddressFamily.InterNetwork);
                  var ep = default(IPEndPoint);
                  while (true)
                  {
                      try
                      {
                          var data = listener.Receive(ref ep);
                          string incomingSyslog = Encoding.ASCII.GetString(data);
                          bgWorker.ReportProgress(0,incomingSyslog);
                      }
                      catch (Exception ex2) { debugLabel1.Text = ex2.ToString(); }
                  }            
              }
              void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
              {
                  debugLabel1.Text = e.UserState as String; //this will eventually be my datagridview code            
              }        
          }
      }
      

      非常感谢这个帖子建议使用UserState传递字符串:C# backgroundWorker reports string?

0 个答案:

没有答案