C# 使用代理实现线程间调用

实现功能:

后台线程改变窗体控件(flowLayoutPanel1)的状态。

利用 this.flowLayoutPanel1.InvokeRequired == false,可以知道是主线程调用的自己控件,还是其他线程调用。

如果其他线程调用就使用DisplayDelegate代理。

窗体初期化时要加,允许线程间调用:

CheckForIllegalCrossThreadCalls = false;

窗体加载时启动一个匿名线程threadStatus,循环监视clientList列表。如果列表中的数值改变则改变窗体控件的状态。

namespace XXXX
{
    public partial class Frm_Manage : Form
    {
        // 客户端状态列表
        Dictionary<string, SocketClientInfo> clientList;
        // 线程间调用代理
        private delegate void DisplayDelegate(string clientIp, string clientNum, string status);
        // 心跳线程
        public Thread threadStatus { set; get; }

        public Frm_Manage()
        {
            // 允许线程间调用
            CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
        }

        private void Frm_Manage_Load(object sender, EventArgs e)
        {
            SocketServer Socketservice = SocketServer.GetInstance();
            clientList = Socketservice.GetClientDictionary();

            threadStatus = new Thread(() =>
            {
                while (true)
                {
                    foreach (SocketClientInfo item in clientList.Values)
                    {
                        bool existFlg = false;
                        foreach (Control subPan in this.flowLayoutPanel1.Controls)
                        {
                            if (subPan.Name == item.clientIp)
                            {
                                // 存在该终端,改变显示状态
                                subPan.BackColor = GetBackColor(item.clientStatus);
                                existFlg = true;
                                break;
                            }
                        }
                        if (!existFlg)
                        {
                            // 不存在该终端,添加新控件
                            AddDisplay(item.clientIp, item.clientNum, item.clientStatus);
                        }
                    }
                    this.flowLayoutPanel1.Refresh();

                    Thread.Sleep(1000 * time);// 间隔1秒刷新页面
                }
            });
            threadStatus.Start();
        }

        private Color GetBackColor(string status)
        {
            if (status == "0")
            {
                return Color.Silver;// 灰色
            }
            else if (status == "1")
            {
                return Color.LawnGreen;// 绿色
            }
            else if (status == "2")
            {
                return Color.Gold;// 黄色
            }
            else if (status == "3")
            {
                return Color.Orange;// 橙色
            }
            else if (status == "4")
            {
                return Color.Red;// 红色
            }
            else
            {
                return Color.Silver;// 灰色
            }
        }

        private void AddDisplay(string clientIp, string clientNum, string status)
        {
            try
            {
                //如果调用该函数的线程和控件flowLayoutPanel1位于同一个线程内
                if (this.flowLayoutPanel1.InvokeRequired == false)
                {
                    //直接将内容添加到窗体的控件上
                    Panel pal = new Panel();
                    pal.Name = clientIp;
                    pal.Width = DisStatusW_PX;
                    pal.Height = DisStatusH_PX;
                    pal.BackColor = GetBackColor(status);
                    pal.Controls.Add(pic);

                    this.flowLayoutPanel1.Controls.Add(pal);
                }
                //如果调用该函数的线程和控件flowLayoutPanel1不在同一个线程
                else
                {
                    //通过使用Invoke的方法,让子线程告诉窗体线程来完成相应的控件操作
                    DisplayDelegate disp = new DisplayDelegate(AddDisplay);

                    //使用控件flowLayoutPanel1的Invoke方法执行Display代理(其类型是DisplayDelegate)
                    this.flowLayoutPanel1.Invoke(disp, clientIp, clientNum, status);
                }
            }
            catch (Exception e)
            {
                LogHelper.WriteError(typeof(Frm_Manage), e);
            }
        }
    }
}
时间: 2024-08-26 01:20:38

C# 使用代理实现线程间调用的相关文章

关于“线程间操作无效: 从不是创建控件’textBox1‘的线程访问它”异常的解决方法

线程间操作无效: 从不是创建控件“textBox1”的线程访问它 背景:通过一个辅助线程计算出的一个值赋给textBox1.text;解决办法:1.直接在窗体的构造函数中加:System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; 此时把所有的控件 合法性线程检查全部都给禁止掉了. 2.通过代理来解决(msdn) private delegate void SetTextCallback(string text);

Android中线程间通信原理分析:Looper,MessageQueue,Handler

自问自答的两个问题 在我们去讨论Handler,Looper,MessageQueue的关系之前,我们需要先问两个问题: 1.这一套东西搞出来是为了解决什么问题呢? 2.如果让我们来解决这个问题该怎么做? 以上者两个问题,是我最近总结出来的,在我们学习了解一个新的技术之前,最好是先能回答这两个问题,这样你才能对你正在学习的东西有更深刻的认识. 第一个问题:google的程序员们搞出这一套东西是为了解决什么问题的?这个问题很显而易见,为了解决线程间通信的问题.我们都知道,Android的UI/Vi

线程间操作无效: 从不是创建控件“”的线程访问它 解决办法(转)

线程间操作无效: 从不是创建控件“”的线程访问它 解决办法 http://blog.sina.com.cn/s/blog_568e66230101der7.html 利用FileSystemWatcher设计一个文件监控系统时,如果一个文件被修改或者新建,则文件修改事件会被多次触发而产生多条信息.为了将一个文件被修改一次而产生的多条信息归结为一条,在设计中新开了一个线程,在指定时间内(如2秒内)这个文件的修改被认为是一次修改,从而只产生一条信息. 这个工作完成后,又出现了另外一个问题:因为需要在

线程间的通信的几种方式

线程间的通信: - 什么叫做线程间通信 - 在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 - 线程间通信的体现 - 1个线程传递数据给另1个线程 - 在1个线程中执行完特定任务后,转到另1个线程继续执行任务 - 线程间通信常用方法 - 方法一:利用perform的方式 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; - (void)

Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当

【转】VC 线程间通信的三种方式

原文网址:http://my.oschina.net/laopiao/blog/94728 1.使用全局变量(窗体不适用)      实现线程间通信的方法有很多,常用的主要是通过全局变量.自定义消息和事件对象等来实现的.其中又以对全局变量的使用最为简洁.该方法将全局变量作为线程监视的对象,并通过在主线程对此变量值的改变而实现对子线程的控制.      由于这里的全局变量需要在使用它的线程之外对其值进行改变,这就需要通过volatile关键字对此变量进行说明.使用全局变量进行线程通信的方法非常简单

线程间的通信、同步方式与进程间通信方式

1.线程间的通信方式 1)使用全局变量(由于多个线程可能更改全局变量,因此全局变量最好声明为volatile) 2) 使用消息实现通信 3)使用事件CEvent类实现线程间的通信 2.同步/异步(C端) 同步:在C端发出一个功能调用时,没有得到结果之前就不返回 异步: 一个请求通过事件触发后,得到服务器处理后才处理完毕 3. 阻塞/非阻塞(S端) 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行).函数只有在得到

Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会引起此共享资源的不一致性.因此,为避免线程安全问题,应该避免多线程环境下对此共享资源的并发访问. 线程安全问题多是由全局变量和静态变量引起的,当多个线程对共享数据只执行读操作,不执行写操作时,一般是线程安全的:当多个线程都执行写操作时,需要考虑线程同步来解决线程安全问题. 二.线程同步(synchr

线程(二)__线程间的通信

线程间的通信:多个线程在处理同一资源,但是任务却不同.一.等待唤醒机制涉及的方法:1.wait();让线程处于冻结状态,被wait的线程会被存储到线程池中2.notify();唤醒线程池中的一个任意线程3.notifyAll();唤醒线程池中的所有线程这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法,必须要明确到底操作的是哪个锁上的线程wait()对A锁上面的线程进行操作后只能用A锁的notify来唤醒.被wait之后的线程可认为放在线程池中. 为什么操作线程的方法wait no