c#winform中多线程怎么轮流执行同一个方法

亚历山大铁憨憨 2017-09-06 04:09:36
需求:用多线程实现多个label同时移动,例如窗口中有六个点,label1从a点移动到b点,label2从c点移动到d点,label3从e点移动到f点
...全文
1360 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 28 楼 xuzuning 的回复:
来一把就事论事 1、从 while (now_x != dic[tag_tim2].Location.X || now_y != dic[tag_tim2].Location.Y) 可以看出运动的终点是 now_x,now_y 而 now_x,now_y 是全局变量,也就是说,所有的 lable 都向同一目标运动,并不是如你说的,各有各的目标 2、ShowNum 方法中的工作变量 pos 也是全局的(各线程共有的)所以你并不能保证在 pos.X = dic[tag_tim2].Location.X; 到 dic[tag_tim2].Location = pos; 期间,pos 不会被其他线程改变 虽然你写有 lock (dic[tag_tim2]),但这是自欺欺人的锁,因为 dic[tag_tim2] 是线程独有的,并不能阻止共享冲突 运行于多线程中的方法,必须是可重入的(不使用全局或内部静态变量保存现场),但你并未做到 所以你的 ShowNum 方法在单线程中能正常运行,但在多线程时就出现种种问题
多谢
  • 打赏
  • 举报
回复
引用 28 楼 xuzuning 的回复:
来一把就事论事 1、从 while (now_x != dic[tag_tim2].Location.X || now_y != dic[tag_tim2].Location.Y) 可以看出运动的终点是 now_x,now_y 而 now_x,now_y 是全局变量,也就是说,所有的 lable 都向同一目标运动,并不是如你说的,各有各的目标 2、ShowNum 方法中的工作变量 pos 也是全局的(各线程共有的)所以你并不能保证在 pos.X = dic[tag_tim2].Location.X; 到 dic[tag_tim2].Location = pos; 期间,pos 不会被其他线程改变 虽然你写有 lock (dic[tag_tim2]),但这是自欺欺人的锁,因为 dic[tag_tim2] 是线程独有的,并不能阻止共享冲突 运行于多线程中的方法,必须是可重入的(不使用全局或内部静态变量保存现场),但你并未做到 所以你的 ShowNum 方法在单线程中能正常运行,但在多线程时就出现种种问题
引用 26 楼 yuhijk2055 的回复:
这符不符合要求
        private void btnStart_Click(object sender, EventArgs e)
        {

            LabThreadMove(label1, new Point(50, 200)); //label1 移动
            LabThreadMove(label2, new Point(150, 200)); //label2 移动
            LabThreadMove(label3, new Point(260, 200)); //label3 移动
        }

        public void LabThreadMove(Label lab, Point point)
        {
            new Thread(delegate () //开后台线程执行移动方法
            {

                while (LabMove(lab, point)) { Thread.Sleep(10); }

            })
            { IsBackground = true }.Start();
        }
        public bool LabMove(Label lab, Point point)
        {
            bool isMove = true;

            this.Invoke((EventHandler)delegate
            {
                if (lab.Location == point)  isMove = false;

                Point curPoint = lab.Location;
                if (curPoint.X != point.X)
                    curPoint.X = curPoint.X - point.X < 0 ? curPoint.X += 1 : curPoint.X -= 1;
                if (curPoint.Y != point.Y)
                    curPoint.Y = curPoint.Y - point.Y < 0 ? curPoint.Y += 1 : curPoint.Y -= 1;

                lab.Location = curPoint;

            });

            return isMove;
        }
多谢大神指点
xuzuning 2017-09-13
  • 打赏
  • 举报
回复
来一把就事论事 1、从 while (now_x != dic[tag_tim2].Location.X || now_y != dic[tag_tim2].Location.Y) 可以看出运动的终点是 now_x,now_y 而 now_x,now_y 是全局变量,也就是说,所有的 lable 都向同一目标运动,并不是如你说的,各有各的目标 2、ShowNum 方法中的工作变量 pos 也是全局的(各线程共有的)所以你并不能保证在 pos.X = dic[tag_tim2].Location.X; 到 dic[tag_tim2].Location = pos; 期间,pos 不会被其他线程改变 虽然你写有 lock (dic[tag_tim2]),但这是自欺欺人的锁,因为 dic[tag_tim2] 是线程独有的,并不能阻止共享冲突 运行于多线程中的方法,必须是可重入的(不使用全局或内部静态变量保存现场),但你并未做到 所以你的 ShowNum 方法在单线程中能正常运行,但在多线程时就出现种种问题
MYsce 2017-09-13
  • 打赏
  • 举报
回复
看不出你这问题跟多线程有什么关系
无情时尚 2017-09-12
  • 打赏
  • 举报
回复
这符不符合要求



        private void btnStart_Click(object sender, EventArgs e)
{

LabThreadMove(label1, new Point(50, 200)); //label1 移动
LabThreadMove(label2, new Point(150, 200)); //label2 移动
LabThreadMove(label3, new Point(260, 200)); //label3 移动
}

public void LabThreadMove(Label lab, Point point)
{
new Thread(delegate () //开后台线程执行移动方法
{

while (LabMove(lab, point)) { Thread.Sleep(10); }

})
{ IsBackground = true }.Start();
}
public bool LabMove(Label lab, Point point)
{
bool isMove = true;

this.Invoke((EventHandler)delegate
{
if (lab.Location == point) isMove = false;

Point curPoint = lab.Location;
if (curPoint.X != point.X)
curPoint.X = curPoint.X - point.X < 0 ? curPoint.X += 1 : curPoint.X -= 1;
if (curPoint.Y != point.Y)
curPoint.Y = curPoint.Y - point.Y < 0 ? curPoint.Y += 1 : curPoint.Y -= 1;

lab.Location = curPoint;

});

return isMove;
}
  • 打赏
  • 举报
回复
这个问题还没解决,求大神指点啊
mk_lucifer 2017-09-07
  • 打赏
  • 举报
回复
没有修改权限,至于写的过程中打错的东西别在意,意会即可。
mk_lucifer 2017-09-07
  • 打赏
  • 举报
回复
引用 5 楼 Android510 的回复:
[quote=引用 3 楼 summergo123321 的回复:] UI对象不支持多线程操作。。 可行方法是,后台创建线程,只执行数据运算,前台线程只修改显示位置即可,不过你的要求优点奇葩,为什么要多线程呢?姑且认为你是为了学习多线程。非要轮流执行某方法的的目的和意义在哪里,我是完全不能理解。
你可以把人比作label,实现多人多位置走动,不知道你有啥好方法[/quote] 你应该找一款物理引擎好好学习学习,都是单线程完成,或者其他自己制作的运动框架,程序都有一个入口函数。格式都是类似。 bool Step(int dt); 其中dt是时间增量,如果你牛顿力学学的足够好,应该明白时间,位移,速度三者的关系。其中参数是dt是时间增量,表示时间又过了多长,那么你可以在Step里根据所有对象的速度,未知给出 t+dt 时刻的位置。算完之后,在UI显示过程中根据对象dt运算过后的当前中心点偏移和旋转角度,尺寸内容变化,等一系列参数重新设置对象属性。 这个过程根本不需要多线程。。 很简单 算法搞这些 label1Info.Pos+=liabel1Info.v*dt; label2Info.Pos+=liabel2Info.v*dt; 前台做一件事 Step(dt) label1.Left=label1Info.S.X label1.Right=label1Info.S.Y label2.Left=label2Info.S.X label2.Right=label2Info.S.Y
ilikeff8 2017-09-07
  • 打赏
  • 举报
回复
如果只是想用些label显示一些文字并不停移动,建议不要用控件做动画,太重了,可以绘制一张bitmap,计算每个文字所在的位置并绘制,然后只显示这张bitmap出来
exception92 2017-09-07
  • 打赏
  • 举报
回复
引用 12 楼 Android510 的回复:
[quote=引用 11 楼 sp1234 的回复:] 先学好“跟线程没有关系”的设计方法,如果遇到问题那恰好说明你没有学会敏捷事件合理安排。 这种界面上物体移动帧跟线程没有关系。
教育人的话谁都会说,但是还要把问题解决掉,希望你能给出实质性强,有用的答案,先上代码,后阐述你的观点,要不然总会让人嗤之以鼻[/quote] 解决问题并不一定都必须上代码呀,有解决思路才有逻辑代码,解决思路不明白,上了代码又有什么用呢。就算贴出了实际代码,难道复制粘贴一下就说明任务”完成”。敢说 十个人里有八个人问题解决了 是不会再回头去看代码逻辑的,所以呢,别激动。
  • 打赏
  • 举报
回复
基本上来说,就算是让你去学习操作控件应该使用 BeginInvoke/Invoke 语句基本知识,其实也可以预计出来你对基本知识也会抱有会有什么反应。 所以这只是提前告诉你该认真理解基础的原理,否则其实你就会一直空洞地停留在刚接触线程概念时的那个阶段。
  • 打赏
  • 举报
回复
不管有多少点,就算是有1万个点需要移动,这些点要在一帧(一次)或者几帧屏幕刷新中进行显示,显示时跟多线程也没有任何关系。 在线程中应该使用 BeginInvoke/Invoke 方式注册更新界面控件的代码,如果不知道这个编程知识背后的原理那么你就不能理解更多了。
exception92 2017-09-07
  • 打赏
  • 举报
回复
引用 6 楼 Android510 的回复:
[quote=引用 2 楼 duanzi_peng 的回复:] 用多线程实现多个label同时移动 -》用3个Timer来控制即可,和多线程没关系。
timer效果不好,这只是三个,如果更多label呢[/quote] 那就用一个timer,因为需要多个label同时移动,在tick方法里同时操作各个lable的location,判断location的位置与目标位置是否一致,一致则停止操作location。
cheng2005 2017-09-07
  • 打赏
  • 举报
回复
引用 12 楼 Android510 的回复:
[quote=引用 11 楼 sp1234 的回复:] 先学好“跟线程没有关系”的设计方法,如果遇到问题那恰好说明你没有学会敏捷事件合理安排。 这种界面上物体移动帧跟线程没有关系。
教育人的话谁都会说,但是还要把问题解决掉,希望你能给出实质性强,有用的答案,先上代码,后阐述你的观点,要不然总会让人嗤之以鼻[/quote] 他的意思很明确了,先不说N个点怎么做,假设就一个点,让你控制这一个点按照路线移动,你会做吗?如果你一个点都不会做,那么扯出什么多线程来你就会做了吗?
  • 打赏
  • 举报
回复
引用 11 楼 sp1234 的回复:
先学好“跟线程没有关系”的设计方法,如果遇到问题那恰好说明你没有学会敏捷事件合理安排。 这种界面上物体移动帧跟线程没有关系。
教育人的话谁都会说,但是还要把问题解决掉,希望你能给出实质性强,有用的答案,先上代码,后阐述你的观点,要不然总会让人嗤之以鼻
易2017 2017-09-07
  • 打赏
  • 举报
回复
看不出你这问题跟多线程有什么关系,机器执行效率这么高,单线程UI刷新就算有先后次序也完全看不出来,而且就算你计算放在后台,最终的UI刷新还是由主线程完成的,http://blog.csdn.net/nnsword/article/details/5543464
正怒月神 2017-09-07
  • 打赏
  • 举报
回复
写了个简单的,你自己看吧。原理是一样的。
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        Control[] ctls = new Control[] {
                new Button(){Text="btn1"},
                new Button(){Text="btn2",Left=100},
                new Button(){Text="btn3",Left=200},
            };
        private void Form1_Load(object sender, EventArgs e)
        {
            this.Controls.AddRange(ctls);

            System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
            t.Interval = 500;
            t.Enabled = true;
            t.Tick += timer1_Tick;
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            //btn1移动
            ctls[0].Top += 5;

            //btn2移动
            ctls[1].Top += 5;
            ctls[1].Left+= 5;

            //btn3移动
            ctls[2].Top += 5;
            ctls[2].Left += -3;
        }


    
    }
并不需要很多个线程。
  • 打赏
  • 举报
回复
引用 13 楼 wddw1986 的回复:
[quote=引用 12 楼 Android510 的回复:] [quote=引用 11 楼 sp1234 的回复:] 先学好“跟线程没有关系”的设计方法,如果遇到问题那恰好说明你没有学会敏捷事件合理安排。 这种界面上物体移动帧跟线程没有关系。
教育人的话谁都会说,但是还要把问题解决掉,希望你能给出实质性强,有用的答案,先上代码,后阐述你的观点,要不然总会让人嗤之以鼻[/quote] 他的意思很明确了,先不说N个点怎么做,假设就一个点,让你控制这一个点按照路线移动,你会做吗?如果你一个点都不会做,那么扯出什么多线程来你就会做了吗?[/quote] 大哥,要是没做出来一个人的,就问一个人的了,如果大哥有好方法不妨分享一下
marmothac 2017-09-07
  • 打赏
  • 举报
回复
引用 19 楼 summergo123321 的回复:
[quote=引用 5 楼 Android510 的回复:] [quote=引用 3 楼 summergo123321 的回复:] UI对象不支持多线程操作。。 可行方法是,后台创建线程,只执行数据运算,前台线程只修改显示位置即可,不过你的要求优点奇葩,为什么要多线程呢?姑且认为你是为了学习多线程。非要轮流执行某方法的的目的和意义在哪里,我是完全不能理解。
你可以把人比作label,实现多人多位置走动,不知道你有啥好方法[/quote] 你应该找一款物理引擎好好学习学习,都是单线程完成,或者其他自己制作的运动框架,程序都有一个入口函数。格式都是类似。 bool Step(int dt); 其中dt是时间增量,如果你牛顿力学学的足够好,应该明白时间,位移,速度三者的关系。其中参数是dt是时间增量,表示时间又过了多长,那么你可以在Step里根据所有对象的速度,未知给出 t+dt 时刻的位置。算完之后,在UI显示过程中根据对象dt运算过后的当前中心点偏移和旋转角度,尺寸内容变化,等一系列参数重新设置对象属性。 这个过程根本不需要多线程。。 很简单 算法搞这些 label1Info.Pos+=liabel1Info.v*dt; label2Info.Pos+=liabel2Info.v*dt; 前台做一件事 Step(dt) label1.Left=label1Info.S.X label1.Right=label1Info.S.Y label2.Left=label2Info.S.X label2.Right=label2Info.S.Y [/quote]
  • 打赏
  • 举报
回复
先学好“跟线程没有关系”的设计方法,如果遇到问题那恰好说明你没有学会敏捷事件合理安排。 这种界面上物体移动帧跟线程没有关系。
加载更多回复(10)

110,532

社区成员

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

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

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