[求助]高分求助,线程的问题!

焱rock 2009-07-09 10:06:48
最近遇到一个项目,需要开发一个winfrom程序,此程序的主要功能是读取USB设备中的数据,并在winfrom中绘制响应曲线.USB设备采集数据的时间可设置,如从10ms---到1s.我遇到的问题如下:当USB采集数据的时间设置为1s时,界面中的按钮控件等响应速度就变慢了.采集USB数据的功能新开了一个线程来接收.按道理讲不会出现影响主界面的情况,但是实际测试时发现USB设备数据采集时间变长时,winform界面响应受到影响,感觉是UI线程在接收数据!请大大们给点指教啊.我这样建立线程的方式是否正确,这样到底算不算开启了一个辅助线程???下面是部分代码,均在Form1.cs文件中:
private bool bool_Isrefreshstop = false;
private delegate void mydelegate();
private mydelegate myfresh;
private delegate void beginInvokeDelegate();
private ThreadStart mystart;
private Thread mythread;
OmniDriver.CCoWrapperClass wrapper=newOmniDriver.CCoWrapperClass();
public double[] spectrumArray, wavelengthArray;
public Form1()
{
InitializeComponent();
sd[0] = new PointPairList();
list_dynamicScan[m_PairListCount] = new PointPairList();
curves[m_PairListCount] = zedGraphControl1.GraphPane.AddCurve("AA", list_dynamicScan[m_PairListCount], Color.Red, SymbolType.None);//在绘图表面上加一条曲线,
WrapperInit();//初始化USB设备
Splasher.Close();
ThreadStart mystart = new ThreadStart(refreshgraph);
mythread = new Thread(mystart);
mythread.IsBackground = true;

}

private void beginInvokeMethod()
{
zedGraphControl1.Invalidate();
}


private void refreshgraph()
{
beginInvokeDelegate hh = new beginInvokeDelegate(beginInvokeMethod);
while (true)
{
if (bool_Isrefreshstop == false)
{
double xCoord = 0, yCoord = 0;
int i;
list_dynamicScan[m_PairListCount].Clear();
sd[0].Clear();
spectrumArray = ((double[])wrapper.getSpectrum(0));// 此处就是读取USB设备数据.
wavelengthArray = ((double[])wrapper.getWavelengths(0));
if (b_Filter == false)
{
for (i = 0; i < spectrumArray.Length; i++)
{
xCoord = Math.Round(((double)wavelengthArray[i]), 2);
yCoord = Math.Round(((double)spectrumArray[i] - (double)spectrumArrayTmp[i]) * 100f / 65535f, 2);// *6000 / ((double)((Int32)wrapper.getMaximumIntensity(0)));
list_dynamicScan[m_PairListCount].Add(xCoord++, yCoord++);
}
}
else
{
for (i = 0; i < spectrumArray.Length; i++)
{
int count = 0;
for (count = 0; count < 15; count++)
{
xCoords[count][i] = xCoords[count + 1][i];
}
xCoords[3][i] = Math.Round(((double)spectrumArray[i]), 2);
xCoord = Math.Round(((double)wavelengthArray[i]), 2);
yCoord = Math.Round(((xCoords[15][i] + xCoords[14][i] + xCoords[13][i] + xCoords[12][i] + xCoords[11][i] + xCoords[10][i] + xCoords[9][i] + xCoords[8][i] + xCoords[7][i] + xCoords[6][i] + xCoords[5][i] + xCoords[4][i] + xCoords[3][i] + xCoords[2][i] + xCoords[1][i] + xCoords[0][i]) / 16 * 100f / 65535f), 2);
list_dynamicScan[m_PairListCount].Add(xCoord, yCoord);
}
}
}
zedGraphControl1.Invoke(hh);
Thread.Sleep(100);
}
}
...全文
162 36 打赏 收藏 转发到动态 举报
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
mabaolin 2009-07-13
  • 打赏
  • 举报
回复
委托和事件并不是新起线程去执行。
fjw8205 2009-07-12
  • 打赏
  • 举报
回复
来学习的,希望继续讨论出个结果,呵呵呵
焱rock 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 istarsoft 的回复:]
设置CheckForIllegalCrossThreadCalls不知会如何?
C# code
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls=false;
[/Quote]
没有用的
焱rock 2009-07-09
  • 打赏
  • 举报
回复
To iStartSoft :我将refreshgraph方法改成如下,情况照旧.
private void refreshgraph()
{

while (true)
{
Application.DoEvents();
spectrumArray = ((double[])wrapper.getSpectrum(0));
Thread.Sleep(100);
}
}
Jock.Chen 2009-07-09
  • 打赏
  • 举报
回复
while(true)过程里加上Application.DoEvents();试下
焱rock 2009-07-09
  • 打赏
  • 举报
回复
while(true)的目的是为了使这个线程一直循环往复的去接收USB设备的数据,直到应用程序退出.此处的接收数据是主动接收,并非下位机不停的往上传数据.
spectrumArray = ((double[])wrapper.getSpectrum(0));// 只有这句代码才使下位机回传数据.
Jock.Chen 2009-07-09
  • 打赏
  • 举报
回复
没看明,"while (true) " 什么时候跳出.

下面我测试的代码:

public partial class frmThread : Form
{
public frmThread()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}

public delegate void PercentCompleteEventHandler(string Message, int Percent);
event PercentCompleteEventHandler PercentComplete;

private void button1_Click(object sender, EventArgs e)
{
m_tspbProgressBar.Value = 0;
m_tspbProgressBar.Minimum = 0;// 进度条
m_tspbProgressBar.Maximum = 100;
m_tspbProgressBar.Visible = true;

PercentComplete = new PercentCompleteEventHandler(Step);
ThreadStart start = new ThreadStart(DataRebateExcute);
start.BeginInvoke(AsyncCallbackMethod,null);


}

/// <summary>
/// 数据处理
/// </summary>
public void DataRebateExcute()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
PercentComplete.Invoke(i.ToString(), i);
}

}

/// <summary>
/// 进度条调整
/// </summary>
public void Step(string Message, int percent)
{
m_tspbProgressBar.Value = percent;
Application.DoEvents();
}

/// <summary>
/// 线程完成后回调
/// </summary>
/// <param name="myIAsyncResult"></param>
public void AsyncCallbackMethod(System.IAsyncResult myIAsyncResult)
{
m_tspbProgressBar.Visible = false;
MessageBox.Show("成功", this.Text,
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
}

grzx2210 2009-07-09
  • 打赏
  • 举报
回复
mark
焱rock 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 hecker728 的回复:]
使用后台线程处理从usb设备读数据

和使用异步通信
[/Quote]
mythread.IsBackground = true; 我现在的线程应该就是后台线程吧?异步通信是使用Begininvoke??
zedGraphControl1.BeginInvoke(hh); ??这样我试过,也不行,还不如invoke呢
chenxiaoguo 2009-07-09
  • 打赏
  • 举报
回复
mark
焱rock 2009-07-09
  • 打赏
  • 举报
回复
hecker728和softlove03,你们到底谁说的对啊?到底同步和异步在我这里有何差别?
hecker728 2009-07-09
  • 打赏
  • 举报
回复
使用后台线程处理从usb设备读数据

和使用异步通信
  • 打赏
  • 举报
回复
一个fifo例子


/*
* 先进先出缓冲
* 缓冲满,丢掉后来的数据
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections;

public class ZDropFifo : IDisposable
{
#region variable
protected Queue m_inputQueue;
protected int 主缓冲长度 = 0;
protected int 允许读取的起始位置 = 0;

protected byte[] 主缓冲 = null;

protected int 写指针 = 0;
protected bool 写位置 = false;
protected int 读指针 = 0;
protected bool 读位置 = false;

//计算位置使用的变量
protected int 到缓冲结尾的距离 = 0;
protected int 剩余的字节长度 = 0;

public bool 可以读 = false;
public int 有效数据长度 = 0;
protected int 写入长度 = -2;
protected int 读取长度 = -2;

int temp = 0;
#endregion

#region public function
public ZDropFifo(int 长度, int 起始)
{
m_inputQueue = new Queue();
主缓冲长度 = 长度;
允许读取的起始位置 = 起始;
主缓冲 = new byte[主缓冲长度];
}

public void Dispose()
{
主缓冲 = null;
m_inputQueue = null;
}

public int 写(byte[] 源, int 源长度)
{
lock (m_inputQueue)
{
//Monitor.Enter(m_inputQueue);
//Console.WriteLine("写");
if (可以读 == false && 写指针 >= 允许读取的起始位置)
可以读 = true;

if (写位置 == 读位置) //写指针 读指针 在同一圈
{
//计算有效数据长度
有效数据长度 = 写指针 - 读指针;
到缓冲结尾的距离 = 主缓冲长度 - 写指针;
剩余的字节长度 = 源长度 - 到缓冲结尾的距离;

if (到缓冲结尾的距离 > 源长度)
{
Buffer.BlockCopy(源, 0, 主缓冲, 写指针, 源长度);
写指针 += 源长度;
//Monitor.Exit(m_inputQueue);
//return 源长度;
写入长度 = 源长度;
}
else //写指针到缓冲结尾的距离<源长度
{
if ((读指针 + 到缓冲结尾的距离) > 源长度)
{
Buffer.BlockCopy(源, 0, 主缓冲, 写指针, 到缓冲结尾的距离);
Buffer.BlockCopy(源, 到缓冲结尾的距离, 主缓冲, 0, 剩余的字节长度);

写指针 = 剩余的字节长度;
写位置 = !写位置;
//Monitor.Exit(m_inputQueue);
//return 源长度;
写入长度 = 源长度;
}
else //读指针 + 到缓冲结尾的距离 < 源长度
{
//Monitor.Exit(m_inputQueue);
//return 0;
写入长度 = 0;
}
}
}
else //写指针 读指针 不在同一圈
{
//计算有效数据长度
有效数据长度 = 主缓冲长度 + 写指针 - 读指针;
剩余的字节长度 = 读指针 - 写指针;

if (剩余的字节长度 > 源长度)
{
Buffer.BlockCopy(源, 0, 主缓冲, 写指针, 源长度);
写指针 += 源长度;
//Monitor.Exit(m_inputQueue);
//return 源长度;
写入长度 = 源长度;
}
else //写指针到读指针的字节长度 < 源长度
{
//Monitor.Exit(m_inputQueue);
//return 0;
写入长度 = 0;
}
}
}
return 写入长度;
}

public int 读(byte[] 目的, int 目的长度)
{
//Monitor.Enter(m_inputQueue);
lock (m_inputQueue)
{
if (可以读)
{
if (写位置 == 读位置)
{
有效数据长度 = 写指针 - 读指针;
if ((写指针 - 读指针) > 目的长度)
{
Buffer.BlockCopy(主缓冲, 读指针, 目的, 0, 目的长度);
读指针 += 目的长度;
//Monitor.Exit(m_inputQueue);
//return 目的长度;
读取长度 = 目的长度;
}
else
{
//Monitor.Exit(m_inputQueue);
//return 0;
读取长度 = 0;
}
}
else
{
有效数据长度 = 主缓冲长度 + 写指针 - 读指针;
到缓冲结尾的距离 = 主缓冲长度 - 读指针;

if (到缓冲结尾的距离 > 目的长度)
{
Buffer.BlockCopy(主缓冲, 读指针, 目的, 0, 目的长度);
读指针 += 目的长度;
//Monitor.Exit(m_inputQueue);
//return 目的长度;
读取长度 = 目的长度;
}
else
{
剩余的字节长度 = 目的长度 - 到缓冲结尾的距离;
if (剩余的字节长度 < 写指针)
{
Buffer.BlockCopy(主缓冲, 读指针, 目的, 0, 到缓冲结尾的距离);
Buffer.BlockCopy(主缓冲, 0, 目的, 到缓冲结尾的距离, 剩余的字节长度);
读指针 = 剩余的字节长度;
读位置 = !读位置;
//Monitor.Exit(m_inputQueue);
//return 目的长度;
读取长度 = 目的长度;
}
else
{
//Monitor.Exit(m_inputQueue);
//return 0;
读取长度 = 0;
}
}
}
}
}
return 读取长度;
}

public byte[] 缓冲区
{
get
{
return 主缓冲;
}
}

#endregion

protected int 加指针(int n)
{
if (写位置 == 读位置)
{
temp = 读指针 + n;
}
else
{
temp = 读指针 + n;
if (temp < 主缓冲长度)
{
//return temp;
}
else
{
temp -= 主缓冲长度;
//return 0;
}
}
return temp;
}
}

  • 打赏
  • 举报
回复
就用上面说的方法实现了。
fifo在网上搜搜,有很多。
多线程一定要使用同步操作的。
焱rock 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 softlove03 的回复:]
引用 13 楼 chenqiyue 的回复:
引用 11 楼 softlove03 的回复:
用了Invoke

是这句话?
  zedGraphControl1.Invoke(hh);



可以这么理解吧。用了Invoke,基本上就失去了多线程的意义。
[/Quote]
我屏蔽掉了这句代码,问题也照旧.唉,郁闷了.兄弟,在帮帮忙啊.小弟刚接触c#,请指教
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 chenqiyue 的回复:]
引用 11 楼 softlove03 的回复:
用了Invoke

是这句话?
  zedGraphControl1.Invoke(hh);

[/Quote]

可以这么理解吧。用了Invoke,基本上就失去了多线程的意义。
焱rock 2009-07-09
  • 打赏
  • 举报
回复
如果我将下面这句代码屏蔽掉,则程序不会出现问题:
spectrumArray = ((double[])wrapper.getSpectrum(0));// 此处就是读取USB设备数据.
而invoke这句似乎影响不大,当采集时间比较长的时候,即便不用invoke程序还是慢.
peterb 2009-07-09
  • 打赏
  • 举报
回复
焱rock 2009-07-09
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 softlove03 的回复:]
用了Invoke
[/Quote]
是这句话?
zedGraphControl1.Invoke(hh);
li365941471 2009-07-09
  • 打赏
  • 举报
回复
mark
加载更多回复(16)

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧