关于C#多线程运行次数的有关问题
关于C#多线程运行次数的问题
各位好:
我的问题是这样的,我有一个WinForm的程序,在程序里跑了10个线程。因为每个线程的执行结果要在WinForm的listbox里显示,所以我加了一把锁,10个线程里的其中一个线程在执行的时候,其他9个全部执行不了在等待。这样会出现一个问题就是某些线程执行次数会很多,而某些线程极端点考虑可能会很久都执行不了一次。我想让这10个线程的执行次数不能说绝对平均,也要是基本平均。想请教下各位有什么办法能解决这个问题。在此谢谢各位。
------解决思路----------------------
检查自己加的锁范围是不是过大了
只有和全局变量,公用变量相关的才需要加锁
局部变量不需要加,本身就是线程安全的
------解决思路----------------------
个人感觉可以换个思路
1. 把要刷新的数据写入队列
2.使用单个线程,从队列去数据,然后刷新
只需要在队列读写加锁,其他地方没有关联,直接无锁
------解决思路----------------------
线程的优先级都一样吗?都设的稍微高一点,还有你刷新listbox频率有多快,每个线程刷新的频率都一样吗?
------解决思路----------------------
你的刷新跟多线程没有毛线关系
你线程执行你的任务
难不成你是在其他线程去刷新控件
如果你是的话,我想问系统没提示你控件不属于该线程吗
------解决思路----------------------
这是你想要的了,这里的线程是绝对平均的了,放到线程里的任务会自动平均分配到对应的线程里
------解决思路----------------------
你确定跨线程访问控件时,多线程会竞争?
本来invoke就回到了UI线程,你再多的线程对listbox操作也无需上锁。
------解决思路----------------------
Control.Invoke 语句本身就是“锁”,它自动地阻塞了(任何)当前子线程,你用不着再加什么锁的。
为了性能考虑,应该尽量使用 Control.BeginInvoke,而不是 Control.Invoke。“加锁、阻塞”的思路往往都是严重影响性能的。
各位好:
我的问题是这样的,我有一个WinForm的程序,在程序里跑了10个线程。因为每个线程的执行结果要在WinForm的listbox里显示,所以我加了一把锁,10个线程里的其中一个线程在执行的时候,其他9个全部执行不了在等待。这样会出现一个问题就是某些线程执行次数会很多,而某些线程极端点考虑可能会很久都执行不了一次。我想让这10个线程的执行次数不能说绝对平均,也要是基本平均。想请教下各位有什么办法能解决这个问题。在此谢谢各位。
------解决思路----------------------
检查自己加的锁范围是不是过大了
只有和全局变量,公用变量相关的才需要加锁
局部变量不需要加,本身就是线程安全的
------解决思路----------------------
个人感觉可以换个思路
1. 把要刷新的数据写入队列
2.使用单个线程,从队列去数据,然后刷新
只需要在队列读写加锁,其他地方没有关联,直接无锁
------解决思路----------------------
线程的优先级都一样吗?都设的稍微高一点,还有你刷新listbox频率有多快,每个线程刷新的频率都一样吗?
------解决思路----------------------
你的刷新跟多线程没有毛线关系
你线程执行你的任务
难不成你是在其他线程去刷新控件
如果你是的话,我想问系统没提示你控件不属于该线程吗
------解决思路----------------------
public class Consumer<T>
{
private int m_Count = 0;
private Iterator<T>[] procHandlers;
public void Init(int iProcesserNum, Action<T> callBack)
{
procHandlers = new Iterator<T>[iProcesserNum];
for (int i = 0; i < iProcesserNum; i++)
{
procHandlers[i] = new Iterator<T>(callBack);
procHandlers[i].Name = i.ToString();
procHandlers[i].Start();
}
}
public void Stop()
{
if (procHandlers != null)
{
for (int i = 0; i < procHandlers.Length; i++)
{
procHandlers[i].Stop();
}
}
}
public void Enqueue(T t)
{
if (m_Count < 0) m_Count = 0;
int index = (int)(m_Count % procHandlers.Length);
procHandlers[index].Enqueue(t);
m_Count++;
}
private class Iterator<TE>
{
private AutoResetEvent m_Signal = new AutoResetEvent(false);
private Queue<TE> m_Queue = new Queue<TE>();
private Thread thread;
private Action<TE> m_CallBack;
private bool isRunning;
public string Name;
public Iterator(Action<TE> callBack)
{
m_CallBack = callBack;
}
public void Start()
{
if (thread == null)
{
isRunning = true;
thread = new Thread(new ThreadStart(SlicProc));
thread.Name = Name;
thread.IsBackground = true;
thread.Start();
}
}
public void Stop()
{
isRunning = false;
if (thread != null)
{
try
{
thread.Abort();
}
finally
{
}
}
thread = null;
}
public void SetSignal()
{
m_Signal.Set();
}
public void Enqueue(TE te)
{
lock (m_Queue)
{
m_Queue.Enqueue(te);
}
m_Signal.Set();
}
private TE Dequeue()
{
lock (m_Queue)
{
if (m_Queue.Count > 0)
{
return m_Queue.Dequeue();
}
}
return default(TE);
}
internal void SlicProc()
{
while (m_Signal.WaitOne())
{
while (m_Queue.Count > 0)
{
TE file = Dequeue();
if (file != null)
{
if (m_CallBack != null)
{
m_CallBack(file);
}
}
}
if (!isRunning)
{
break;
}
}
}
}
}
//调用DEMO
定义为静态
private static Consumer<实体参数> consumerProc = new Consumer<实体参数>();
consumerProc.Init(3, Proc);//初始化3个线程执行,Proc为处理方法
private static void Proc(实体参数 handler)
{
这里干话你平常怎么干就怎么干
}
下面这句放到你读取数据库的线程中读取后直接把你的实体参数放到这个里面,线程一有空闲就会接收并马上处理
consumerProc.Enqueue(实体参数);//
这是你想要的了,这里的线程是绝对平均的了,放到线程里的任务会自动平均分配到对应的线程里
------解决思路----------------------
你确定跨线程访问控件时,多线程会竞争?
本来invoke就回到了UI线程,你再多的线程对listbox操作也无需上锁。
------解决思路----------------------
Control.Invoke 语句本身就是“锁”,它自动地阻塞了(任何)当前子线程,你用不着再加什么锁的。
为了性能考虑,应该尽量使用 Control.BeginInvoke,而不是 Control.Invoke。“加锁、阻塞”的思路往往都是严重影响性能的。