我正在开发一个持续监听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线程退出。
所以我想我的问题可以用两种方式表达:
和/或
更新 我转储了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?