2 huangchao2011 huangchao2011 于 2017.01.04 16:11 提问

C#并行任务出现卡死的问题

我想实现的结果很简单,就是用并行的方式去为2个控件赋值,但是结果是窗体会假死,看起来是死锁的样子,不懂为什么,谁能给讲解讲解一下。
代码:

 private void button4_Click(object sender, EventArgs e)
        {
            Parallel.Invoke(
               SetLable1Text,
               SetLable2Text
                );
        }

        void SetLable1Text()
        {
            label1.Invoke(new Action(() => {
                label1.Text = "正在执行...";
                Thread.Sleep(TimeSpan.FromSeconds(3));
                label1.Text = "执行完毕";
            }));
        }

        void SetLable2Text()
        {
            label2.Invoke(new Action(() =>
            {
                label2.Text = "正在执行...";
                Thread.Sleep(TimeSpan.FromSeconds(2));
                label2.Text = "执行完毕";
            }));
        }

2个回答

qq_21020791
qq_21020791   2017.01.04 16:46

Thread.Sleep()阻塞了GUI线程,所以窗体假死了。

u012046379
u012046379   2017.01.05 12:30

你 Parallel.Invoke 在主线程中调用的,要等到invoke参数里所有任务执行完成后 主线程才返回。经过测试,invoke参数里面的第一个任务始终是在主线程中执行的,所以修改UI能成功,而后面的任务在其他线程执行。当第二个任务开始的时候,在调用label2.Invoke的时候 是子线程请求主线程更新UI,但是主线程现在没有返回只能继续等待。主线程也在等待所有任务完成后返回(主线程等待任务二完成后返回,任务二在等待主线程完成后更新UI所以任务二永远没法完成)造成死锁
解决办法:
一.都用BeginInvoke

  void SetLable2Text()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":"+Thread.CurrentThread.ThreadState.ToString());
                label2.Invoke(new Action(() =>
                {

                // Thread.Sleep(TimeSpan.FromSeconds(2));
                label2.Text = "执行完毕";
                    Console.WriteLine("Method=2, Thread={0}", Thread.CurrentThread.ManagedThreadId);


                }));
            }

二. 把Parallel.Invoke放到子线程
ThreadPool.QueueUserWorkItem(w =>
{
tThread.ThreadState.ToString());
Parallel.Invoke(
()=> { Console.WriteLine("Lable1:coutn:0" + "," + Thread.CurrentThread.ManagedThreadId + ":" + Thread.CurrentThread.ThreadState.ToString()); },
SetLable2Text,
SetLable1Text
);
});

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
C#并行编程--并行任务
并行任务的概念(from  msdn) 任务并行库 (TPL) 基于任务的概念。 术语“任务并行”是指一个或多个独立的任务同时运行。 任务表示异步操作,在某些方面它类似于创建新线程或 ThreadPool 工作项,但抽象级别较高。 任务提供两个主要好处: 系统资源的使用效率更高,可伸缩性更好。 在后台,任务排队到 ThreadPool,ThreadPool 已使用登山等算
C# 4.0的并行任务
C# 4.0支持并行任务,并行任务能提高CPU的利用率(尤其是当前CPU基本都是多核情况下),缩短处理时间,代码取自: http://www.dotnetjalps.com/2012/12/Parallel-task-with-task-parallel-library-in-Csharp.html http://www.cnblogs.com/luminji/archive/2011/
C# 并行任务——Parallel类
https://www.cnblogs.com/ricky-wang/p/7003162.html一、Parallel类      Parallel类提供了数据和任务的并行性;二、Paraller.For()      Paraller.For()方法类似于C#的for循环语句,也是多次执行一个任务。使用Paraller.For()方法,可以并行运行迭代,迭代的顺序没有定义。      在For(...
C# 多线程防止卡死
软件界面的响应特性是判断一款软件的非常重要的方面。一般来说,不管你软件功能做得有多么奇妙,如果软件有一点点死机的感觉都会让用户感到很讨厌,甚至怀疑你软件里是否藏有更大的问题。     要提高界面的响应特性,最好的办法莫过于使用多线程,并把呈现界面的线程独立出来。以前只有使用C++才能实现的多线程功能,现在在.Net框架下,所有的语言(包括VB)都可以使用了。不过,使用多线程比使用单一线程
C# 关闭串口卡死
用C#编写的wince串口通信程序基本大功告成了,与之前用API函数和线程来做串口通信不同,这次直接使用SerialPort控件来做,原本以为使用控件做会简单和方便许多,没成想,还遇到了很多麻烦。        通信协议解析判断、控件数据更新显示等等都没有给我造成什么障碍,却偏偏在“关闭串口”这个地方卡壳了。        在网上看了很多帖子,发现遇到这一问题的人还比较多,按他们的建议和方法都
c#多线程防止界面卡死
当我们的界面需要在程序运行中不断更新数据时,当一个textbox的数据需要变化时,为了让程序执行中不出现界面卡死的现像,最好的方法就是多线程来解决 一个主线程来创建界面,使用一个子线程来执行程序并更新主界面 这个问题其实也困或了我很久,但是今天终于解决了,而且我发现很多人有这样的问题,所以我分享一个例子方便大家参考吧。 先来看看我的界面 当我点击开启线程后 下面是我的
C#多线程解决界面卡死问题的完美解决方案
C#多线程解决界面卡死问题的完美解决方案
C#用了多线程界面卡死
C#用了多线程界面卡死
c#中多线程写DataGridView出现滚动条导致程序卡死(无响应)的解决办法
在多线程修改DataGridView的时候,一旦出现滚动条貌似程序就会扑街。。。具体的原理不知道是啥,只给出一种可行的解决方案~
C# 解决串口关闭时程序卡死问题
关于串口关闭原理的资料:http://blog.csdn.net/wuyazhe/article/details/5606276 个人使用解决方案,将Invoke变为BeginInvoke。