C#,在单独的线程中解析数据并更新 GUI
C#, parsing data in a separate thread and updating GUI
大家。基本上我要实现的工作流程如下:
由于截止日期不远,我从一个名为 Termie 的开源项目开始,它实现了一个简单的串行接口,还提供了一个开箱即用的通信配置表单。
为了执行多线程操作,我使用了 BackgroundWorker
private BackgroundWorker backgroundPressure = new BackgroundWorker();
我在主窗体的构造方法中初始化的:
public consoleForm()
{
...
// Initialize background worker to separate GUI from data collection
backgroundPressure.DoWork += new DoWorkEventHandler(backgroundPressure_DoWork);
backgroundPressure.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundPressure_RunWorkerCompleted);
backgroundPressure.ProgressChanged += new ProgressChangedEventHandler(backgroundPressure_ProgressChanged);
backgroundPressure.WorkerReportsProgress = true;
backgroundPressure.WorkerSupportsCancellation = true;
}
传输开始时,调用backgroundPressure的RunworkerAsync方法:
if(!backgroundPressure.IsBusy)
{
backgroundPressure.RunWorkerAsync();
}
正确处理了DoWork事件,我的程序正确地进入了具有以下代码的处理程序方法:
protected void backgroundPressure_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker sendingWorker = (BackgroundWorker)sender;
BeginInvoke((MethodInvoker)delegate
{
pressureChart.Series.Clear();
pressureData.Clear();
timeAxis.Clear();
foreach (string name in pressureSensorNames)
{
pressureChart.Series.Add(name);
}
});
Stopwatch sto = new Stopwatch();
int linenumber = syncWithLogger("pres");
int debugs = linenumber;
while (linenumber == -1)
{
Thread.Sleep(100);
BeginInvoke((MethodInvoker)delegate
{
linenumber = syncWithLogger("pres");
});
}
sto.Start();
long elapsed = sto.ElapsedMilliseconds;
while (!sendingWorker.CancellationPending)
{
BeginInvoke((MethodInvoker)delegate
{
try
{
elapsed = sto.ElapsedMilliseconds;
pressureChartUpdate(linenumber, elapsed);
imuChartUpdate(linenumber + 1, elapsed);
linenumber += 2;
Thread.Sleep(100);
}
catch(Exception ex)
{
if(ex is FormatException)
{
Thread.Sleep(100);
// Wait and go on
}
else if(ex is ArgumentOutOfRangeException)
{
Thread.Sleep(100);
// Wait and go on
}
}
});
sendingWorker.ReportProgress(10, 100);
BeginInvoke((MethodInvoker)delegate
{
samplesAcquiredStatus.Text = sto.ElapsedMilliseconds.ToString();
});
e.Cancel = true;
sto.Stop();
}
}
一切正常,直到 while (!sendingWorker.CancellationPending)
块。当它进入时,GUI 冻结并且 Visual Studio 报告内存占用逐渐和快速增加,我真的不明白,同时没有抛出异常。
如果我注释掉调用 GUI 更新方法的代码,也会发生这种行为
pressureChartUpdate(linenumber, elapsed);
imuChartUpdate(linenumber + 1, elapsed);
我已经单独测试了解析器,所以我认为问题出在多线程操作上。谁能帮帮我?
一个问题是在 UI 线程上调用 Thread.Sleep
。根据定义,这将阻止您的 UI 并使其无响应。一旦进入休眠状态,它就无法执行任何操作。
大家。基本上我要实现的工作流程如下:
由于截止日期不远,我从一个名为 Termie 的开源项目开始,它实现了一个简单的串行接口,还提供了一个开箱即用的通信配置表单。 为了执行多线程操作,我使用了 BackgroundWorker
private BackgroundWorker backgroundPressure = new BackgroundWorker();
我在主窗体的构造方法中初始化的:
public consoleForm()
{
...
// Initialize background worker to separate GUI from data collection
backgroundPressure.DoWork += new DoWorkEventHandler(backgroundPressure_DoWork);
backgroundPressure.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundPressure_RunWorkerCompleted);
backgroundPressure.ProgressChanged += new ProgressChangedEventHandler(backgroundPressure_ProgressChanged);
backgroundPressure.WorkerReportsProgress = true;
backgroundPressure.WorkerSupportsCancellation = true;
}
传输开始时,调用backgroundPressure的RunworkerAsync方法:
if(!backgroundPressure.IsBusy)
{
backgroundPressure.RunWorkerAsync();
}
正确处理了DoWork事件,我的程序正确地进入了具有以下代码的处理程序方法:
protected void backgroundPressure_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker sendingWorker = (BackgroundWorker)sender;
BeginInvoke((MethodInvoker)delegate
{
pressureChart.Series.Clear();
pressureData.Clear();
timeAxis.Clear();
foreach (string name in pressureSensorNames)
{
pressureChart.Series.Add(name);
}
});
Stopwatch sto = new Stopwatch();
int linenumber = syncWithLogger("pres");
int debugs = linenumber;
while (linenumber == -1)
{
Thread.Sleep(100);
BeginInvoke((MethodInvoker)delegate
{
linenumber = syncWithLogger("pres");
});
}
sto.Start();
long elapsed = sto.ElapsedMilliseconds;
while (!sendingWorker.CancellationPending)
{
BeginInvoke((MethodInvoker)delegate
{
try
{
elapsed = sto.ElapsedMilliseconds;
pressureChartUpdate(linenumber, elapsed);
imuChartUpdate(linenumber + 1, elapsed);
linenumber += 2;
Thread.Sleep(100);
}
catch(Exception ex)
{
if(ex is FormatException)
{
Thread.Sleep(100);
// Wait and go on
}
else if(ex is ArgumentOutOfRangeException)
{
Thread.Sleep(100);
// Wait and go on
}
}
});
sendingWorker.ReportProgress(10, 100);
BeginInvoke((MethodInvoker)delegate
{
samplesAcquiredStatus.Text = sto.ElapsedMilliseconds.ToString();
});
e.Cancel = true;
sto.Stop();
}
}
一切正常,直到 while (!sendingWorker.CancellationPending)
块。当它进入时,GUI 冻结并且 Visual Studio 报告内存占用逐渐和快速增加,我真的不明白,同时没有抛出异常。
如果我注释掉调用 GUI 更新方法的代码,也会发生这种行为
pressureChartUpdate(linenumber, elapsed);
imuChartUpdate(linenumber + 1, elapsed);
我已经单独测试了解析器,所以我认为问题出在多线程操作上。谁能帮帮我?
一个问题是在 UI 线程上调用 Thread.Sleep
。根据定义,这将阻止您的 UI 并使其无响应。一旦进入休眠状态,它就无法执行任何操作。