zoukankan      html  css  js  c++  java
  • 多线程Crossthread的问题

         最近在用C#做网络通信方面的WinForm程序,是C/S架构的程序,用到了多线程处理两端的通信。今天在调试的时候碰到了一个异常:Cross-thread operation not valid: Control 'btnConnect' accessed from a thread other than the thread it was created on.在线程上出问题了,但是在不调试的时候使用是正常的。于是去网上搜索,又查了MSDN,原来是跨线程的问题。编译器只允许创建win form控件的线程去改变这个控件。
            解决方法有两个


    1.在main()中加入Control.CheckForIllegalCrossThreadCalls = false,这是比较偷懒的方法了,因为问题还存在,只是VS不报异常而已了。
    2.使用委托,加入如下代码
            public delegate void SetTextCallback(string text);

            private void SetText(string text)
            {
                if (this.ListStatusLog.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(SetText);
                    ListStatus.BeginInvoke(d, new object[] { text });
                }
                else
                {
                    ListStatus.Items.Add(text) ;
                }
            }
    然后再调用SetText("text");

    C#2005后不再支持多线程直接访问界面的控件(界面创建线程与访问线程不是同一个线程),不过可以使用delegate来解决:

    1. 声明一个delegate和定义一个delegate的实现函数
    delegate void ShowProgressDelegate(int newPos);
    private void ShowProgress(int newPos)
    {
    // 判断是否在线程中访问
    if (!_progressBar.InvokeRequired)
    {
    // 不是的话直接操作控件
    _progressBar.Value = newPos;
    }
    else
    {
    // 是的话启用delegate访问
    ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress);
    // 如使用Invoke会等到函数调用结束,而BeginInvoke不会等待直接往后走
    this.BeginInvoke(showProgress, new object[] { newPos });
    }
    }

    2. 定义线程函数(在另一个线程中可以对界面控件进读操作)
    private void ProgressStart()
    {
    while (true)
    {
    int newPos = _progressBar.Value + 10;

    if (newPos > _progressBar.Maximum)
    {
    newPos = _progressBar.Minimum;
    }
    Trace.WriteLine(string.Format("Pos: {0}", newPos));

    // 这里直接调用方法,由其内部自动判断是否启用delegate
    ShowProgress(newPos);
    Thread.Sleep(100);
    }
    }

    3. 线程的启动和终止
    private Thread _progressThread;
    _progressThread = new Thread(new ThreadStart(ProgressStart));
    // 可选,功用:即使该线程不结束,进程也可以结束
    _progressThread.IsBackground = true;
    _progressThread.Start();

    _progressThread.Abort();
    // 可选,功用:等到线程结束才继续
    _progressThread.Join();
    _progressThread = null;

  • 相关阅读:
    Spring HTTP Service
    Nexus搭建Maven私服
    虚拟机Class文件结构笔记
    JVM内存区域与内存溢出异常
    深入学习虚拟机类加载过程
    虚拟机常用的内存查看与分析工具
    对Java内存模型即JMM的理解
    通过Redux源码学习基础概念一:简单例子入门
    跟着官网的例子学Reacjs (一)FilterableProductTable
    es6继承 vs js原生继承(es5)
  • 原文地址:https://www.cnblogs.com/Safe3/p/1357312.html
Copyright © 2011-2022 走看看