关于C#多线程运行次数的问题

chenmozhijin 2015-04-21 09:08:23
各位好:
我的问题是这样的,我有一个WinForm的程序,在程序里跑了10个线程。因为每个线程的执行结果要在WinForm的listbox里显示,所以我加了一把锁,10个线程里的其中一个线程在执行的时候,其他9个全部执行不了在等待。这样会出现一个问题就是某些线程执行次数会很多,而某些线程极端点考虑可能会很久都执行不了一次。我想让这10个线程的执行次数不能说绝对平均,也要是基本平均。想请教下各位有什么办法能解决这个问题。在此谢谢各位。
...全文
327 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
john_QQ:2335298917 2015-04-21
  • 打赏
  • 举报
回复
线程的优先级都一样吗?都设的稍微高一点,还有你刷新listbox频率有多快,每个线程刷新的频率都一样吗?
xian_wwq 2015-04-21
  • 打赏
  • 举报
回复
引用 4 楼 chenmozhijin 的回复:
TO xian_wwq 我加锁的原因其实就是因为listbox同一时间只能一个线程访问。如果不是这个原因不用加锁也没事,如果这个程序不需要输出日志到文本文件和在listbox上显示操作记录,我就直接用你命令提示符的界面去做了,这样就不存在我今天问的这个问题了。
个人感觉可以换个思路 1. 把要刷新的数据写入队列 2.使用单个线程,从队列去数据,然后刷新 只需要在队列读写加锁,其他地方没有关联,直接无锁
chenmozhijin 2015-04-21
  • 打赏
  • 举报
回复
TO xian_wwq 我加锁的原因其实就是因为listbox同一时间只能一个线程访问。如果不是这个原因不用加锁也没事,如果这个程序不需要输出日志到文本文件和在listbox上显示操作记录,我就直接用你命令提示符的界面去做了,这样就不存在我今天问的这个问题了。
chenmozhijin 2015-04-21
  • 打赏
  • 举报
回复
但是没办法啊,listbox同一时间只能一个线程访问啊。我也不想啊
QQ234788028 2015-04-21
  • 打赏
  • 举报
回复
那你搞多线程有意义吗,还不是一个一个来执行。
xian_wwq 2015-04-21
  • 打赏
  • 举报
回复
检查自己加的锁范围是不是过大了 只有和全局变量,公用变量相关的才需要加锁 局部变量不需要加,本身就是线程安全的
  • 打赏
  • 举报
回复
Control.Invoke 语句本身就是“锁”,它自动地阻塞了(任何)当前子线程,你用不着再加什么锁的。 为了性能考虑,应该尽量使用 Control.BeginInvoke,而不是 Control.Invoke。“加锁、阻塞”的思路往往都是严重影响性能的。
暈哥 2015-04-21
  • 打赏
  • 举报
回复
引用 4 楼 chenmozhijin 的回复:
TO xian_wwq 我加锁的原因其实就是因为listbox同一时间只能一个线程访问。如果不是这个原因不用加锁也没事,如果这个程序不需要输出日志到文本文件和在listbox上显示操作记录,我就直接用你命令提示符的界面去做了,这样就不存在我今天问的这个问题了。
你确定跨线程访问控件时,多线程会竞争? 本来invoke就回到了UI线程,你再多的线程对listbox操作也无需上锁。
本拉灯 2015-04-21
  • 打赏
  • 举报
回复

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(实体参数);//

这是你想要的了,这里的线程是绝对平均的了,放到线程里的任务会自动平均分配到对应的线程里
chenmozhijin 2015-04-21
  • 打赏
  • 举报
回复
To mervyn807 系统没提示你控件不属于该线程,这个问题不存在解决了
缭绕飘渺 2015-04-21
  • 打赏
  • 举报
回复
你的刷新跟多线程没有毛线关系 你线程执行你的任务 难不成你是在其他线程去刷新控件 如果你是的话,我想问系统没提示你控件不属于该线程吗
wish907 2015-04-21
  • 打赏
  • 举报
回复
这个本质上还是单线程啊
chenmozhijin 2015-04-21
  • 打赏
  • 举报
回复
TO johnliuyuan 10个线程里面有5个刷新频率是一样的,另外5个3个是一样的,剩下的2个是一样的。

110,538

社区成员

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

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

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