我是编码游戏的新手,所以我不太清楚如何解决这个问题。我的代码从一个线程中提取信息,该线程从9DOF传感器中获取数据,该传感器以三个欧拉角出现。然后使用该数据生成点,在该点上使用绘图类在屏幕上创建圆。要完美地工作一段时间,但最终总会给出这个异常,说在System.Drawing.dll中发生了一个未处理的“System.InvalidOperationException”类型的异常,其中包含附加信息,说明该对象当前正在其他地方使用。在进行了更多的讨论并使用绘制的内容后,我得出(可能不正确的)结论,即线程发送的数据比主代码可以渲染绘图的速度快。我怎么能阻止这个?下面是代码的摘录。
private void button3_Click(object sender, EventArgs e)
{
//single node test
Nodes.NodesList.Add(new RazorIMU("COM7"));
Nodes.NodesList[0].StartCollection('e');
Nodes.NodesList[0].CapturedData += new RazorDataCaptured(Fusion_CapturedData);
public void Fusion_CapturedData(float[] data, float deltaT)
{
int centerX = (int)(300 + (5 / 3) * data[0] + 0.5);
int centerY = (int)(300 + (5 / 3) * data[1] + 0.5);
int endPointX = (int)(centerX + 25 * Math.Sin(Math.PI / 180 * data[2]) + 0.5);
int endPointY = (int)(centerY + 25 * Math.Cos(Math.PI / 180 * data[2]) + 0.5);
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(bmp))
{
/*g.DrawLine(new Pen(Color.Yellow), 300, 0, 300, 600);
g.DrawLine(new Pen(Color.Yellow), 0, 300, 600, 300);
g.DrawLine(new Pen(Color.LightYellow), 150, 0, 150, 600);
g.DrawLine(new Pen(Color.LightYellow), 0, 150, 600, 150);
g.DrawLine(new Pen(Color.LightYellow), 450, 0, 450, 600);
g.DrawLine(new Pen(Color.LightYellow), 0, 450, 600, 450);*/
g.DrawEllipse(new Pen(Color.Green), centerX - 25, centerY - 25, 50, 50);
g.DrawLine(new Pen(Color.Green), centerX, centerY, endPointX, endPointY);
}
pictureBox1.Image = bmp;
}
这是主要代码。线程只是以收到信息的速度发送信息,所以除非有人另有说法,否则我认为我不需要把它放在这里。
{ public delegate void RazorDataCaptured(float [] data,float deltaT);
/// <summary>
///
/// Object for Sparkfun's 9 Degrees of Freedom - Razor IMU
/// Product ID SEN-10736
/// https://www.sparkfun.com/products/10736
///
/// Running Sample Firmware
/// https://github.com/a1ronzo/SparkFun-9DOF-Razor-IMU-Test-Firmware
///
/// </summary>
public class RazorIMU : IDisposable
{
private SerialPort _com;
private static byte[] TOGGLE_AUTORUN = new byte[] { 0x1A };
public string Port { get; private set; }
private Thread _updater;
private string[] _parts;
public event RazorDataCaptured CapturedData = delegate { };
private float[] _data = new float[9];
private static bool running = false;
/// <summary>
/// Create a new instance of a 9DOF Razor IMU
/// </summary>
/// <param name="portName">Serial port name. Ex: COM1.</param>
public RazorIMU(string portName)
{
// Create and open the port connection.
_com = new SerialPort(portName, 57600, Parity.None, 8, StopBits.One);
_com.Open();
Port = portName;
// Set the IMU to automatically collect data if it has not done yet.
//Thread.Sleep(3000);
//_com.Write("#s00");
//_com.DiscardInBuffer();
}
/// <summary>
/// Start continuous collection of data.
/// </summary>
public void StartCollection(char dataType)
{
running = true;
if (dataType == 'r') _updater = new Thread(new ThreadStart(ContinuousCollect));
else if (dataType == 'q') _updater = new Thread(new ThreadStart(ContinuousCollectQuat));
else if (dataType == 'e') _updater = new Thread(new ThreadStart(ContinuousCollectEuler));
_updater.Start();
}
/// <summary>
/// Stop continuous collect of data.
/// </summary>
public void StopCollection()
{
if (_updater != null)
{
running = false;
_updater.Join();
_updater = null;
}
}
/// <summary>
/// This method is extremely important. It continously updates the data array.
/// Data is read and the change in time since the last read is calculated.
/// The CapturedData event is triggered, sending the new data and the change in time.
/// </summary>
private void ContinuousCollect()
{
_com.WriteLine("#osr"); //Sets sensor output data to raw.
_com.ReadLine(); //Discards first line if broken.
while (running) //Static Boolean that controls whether or not to keep running.
{
ReadDataRaw();
CapturedData(_data, 0.020F);
}
}
private void ContinuousCollectQuat()
{
_com.WriteLine("#ot"); //Sets sensor output data to quaternions.
_com.ReadLine(); //Discards first line if broken.
while (running) //Static Boolean that controls whether or not to keep running.
{
ReadDataQuat();
CapturedData(_data, 0.020F);
}
}
private void ContinuousCollectEuler()
{
_com.WriteLine("#ob"); //Sets sensor output data to quaternions.
_com.ReadLine(); //Discards first line if broken.
while (running) //Static Boolean that controls whether or not to keep running.
{
ReadDataEuler();
CapturedData(_data, 0.020F);
}
}
/// <summary>
/// Get a single sample of the 9DOF Razor IMU data.
/// <para>Format: [accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z]</para>
/// </summary>
/// <param name="result">double array of length 9 required.</param>
private void ReadDataRaw()
{
_parts = _com.ReadLine().Split(',');
if (_parts.Length == 9)
for (int i = 0; i < 9; i++)
_data[i] = float.Parse(_parts[i]);
}
private void ReadDataQuat()
{
_parts = _com.ReadLine().Split(',');
if (_parts.Length == 4)
for (int i = 0; i < 4; i++)
_data[i] = float.Parse(_parts[i]);
}
private void ReadDataEuler()
{
_parts = _com.ReadLine().Split(',');
if (_parts.Length == 3)
for (int i = 0; i < 3; i++)
_data[i] = float.Parse(_parts[i]);
}
/// <summary>
///
/// </summary>
public void Dispose()
{
StopCollection();
if (_com != null) //Make sure _com exists before closing it.
_com.Close();
_com = null;
_data = null;
_parts = null;
}
}
}
答案 0 :(得分:0)
问题:
Invoke
。您可以将此简单模板用于Form
内的事件处理程序(将其应用于Fusion_CapturedData()
):
public void SomeEventHandler(someparameters)
{
if (InvokeRequired)
Invoke((Action)(() => SomeEventHandler(someparameters))); // invoke itself
else
{
... // put code which should run in UI thread here
}
}
你正在同步上升事件,它不可能在另一个完成之前完成(就我所见,不需要同步)。