zoukankan      html  css  js  c++  java
  • 线程间操作无效: 从不是创建控件“”的线程访问它

    线程间操作无效: 从不是创建控件“”的线程访问它。
    听说2003里边不会,我不知道是不是这样的,反正一直都在用05~
    05里会出这个问题的,貌似是为了安全~
    哦,现在知道的解决方法有两个~

    第一:

    Control.CheckForIllegalCrossThreadCalls = false;


    线程开始的时候加这么一句,OK,看不到错误了~
    啥都能用了~

    第二:
    用委托,在05里,每个控件都有个InvokeRequired的属性~
    判断一下是不是true,是的话进行Invoke操作的,完事了~

    //建立个委托
    private delegate string returnStrDelegate();

    //
    搞个最简单滴取值滴方法~
    private string returnSchool()
            
    {
                
    return CB_School.SelectedValue.ToString();
            }


    //
    判断一下是不是该用Invoke滴~,不是就直接返回~
    private string returnCB(returnStrDelegate myDelegate)
            
    {
                
    if (this.InvokeRequired)
                
    {
                    
    return (string)this.Invoke(myDelegate);
                }

                
    else
                
    {
                    
    return myDelegate();
                }

            }


    //
    别的线程里的调用哇~
    string _school = returnCB(returnSchool);

    在进行线程方面的编程的时,遇到这样的错误 "线程间操作无效:从不是创建控件“XX”的线程访问它"

    解决方法:

    在构造函数中加入如下代码:CheckForIllegalCrossThreadCalls    =    false;

    访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。

    .NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。”

    此异常在调试期间和运行时的某些情况下可靠地发生。强烈建议您在显示此错误信息时修复此问题。在调试以 .NET Framework 2.0 版之前的 .NET Framework 编写的应用程序时,可能会出现此异常。 注意 可以通过将 CheckForIllegalCrossThreadCalls 属性的值设置为 false 来禁用此异常。这会使控件以与在 Visual Studio 2003 下相同的方式运行。 下面的代码示例演示如何从辅助线程以线程安全方式和非线程安全方式调用 Windows 窗体控件。它演示一种以非线程安全方式设置 TextBox 控件的 Text 属性的方法,还演示两种以线程安全方式设置 Text 属性的方法。

    using System;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Forms;
    namespace CrossThreadDemo
    {
    public class Form1 : Form
    {
    // 代理实现异步调用以设置TextBox控件text属性
    delegate void SetTextCallback(string text);
    // 此线程用来演示线程安全和非安全两种方式来调用一个windows窗体控件
    private Thread demoThread = null;
    // 此后台工作者(BackgroundWorker)用来演示执行异步操作的首选方式
    private BackgroundWorker backgroundWorker1;
    private TextBox textBox1;
    private Button setTextUnsafeBtn;
    private Button setTextSafeBtn;
    private Button setTextBackgroundWorkerBtn;
    private System.ComponentModel.IContainer components = null;
    public Form1()
    {
    InitializeComponent();
    }
    protected override void Dispose(bool disposing)
    {
    if (disposing && (components != null))
    {
    components.Dispose();
    }
    base.Dispose(disposing);
    }
    // 此事件句柄创建一个ie线程以非安全方式调用一个windows窗体控件
    private void setTextUnsafeBtn_Click(
    object sender,
    EventArgs e)
    {
    this.demoThread =
    new Thread(new ThreadStart(this.ThreadProcUnsafe));
    this.demoThread.Start();
    }
    // 此方法在工作者线程执行并且对TextBox控件作非安全调用
    		private void ThreadProcUnsafe()
    {
    this.textBox1.Text = "This text was set unsafely.";
    }
    // 此事件句柄创建一个以线程安全方式调用windows窗体控件的线程
    private void setTextSafeBtn_Click(
    object sender,
    EventArgs e)
    {
    this.demoThread =
    new Thread(new ThreadStart(this.ThreadProcSafe));
    this.demoThread.Start();
    }
    // 此方法在工作者线程执行并且对TextBox控件作线程安全调用
    private void ThreadProcSafe()
    {
    this.SetText("This text was set safely.");
    }
    // 此方法演示一个对windows窗体控件作线程安全调用的模式
    //
    // 如果调用线程和创建TextBox控件的线程不同,这个方法创建
    // 代理SetTextCallback并且自己通过Invoke方法异步调用它
    // 如果相同则直接设置Text属性
    private void SetText(string text)
    {
    // InvokeRequired需要比较调用线程ID和创建线程ID
    // 如果它们不相同则返回true
    if (this.textBox1.InvokeRequired)
    {
    SetTextCallback d = new SetTextCallback(SetText);
    this.Invoke(d, new object[] { text });
    }
    else
    {
    this.textBox1.Text = text;
    }
    }
    // 此事件句柄通过调用RunWorkerAsync开启窗体的BackgroundWorker
    //
    // 当BackgroundWorker引发RunworkerCompleted事件的时候TextBox
    // 控件的Text属性被设置
    private void setTextBackgroundWorkerBtn_Click(
    object sender,
    EventArgs e)
    {
    this.backgroundWorker1.RunWorkerAsync();
    }
    // 此事件句柄设置TextBox控件的Text属性,它在创建TextBox控件的线程
    // 中被调用,所以它的调用是线程安全的
    //
    // BackgroundWorker是执行异步操作的首选方式
    private void backgroundWorker1_RunWorkerCompleted(
    object sender,
    RunWorkerCompletedEventArgs e)
    {
    this.textBox1.Text =
    "This text was set safely by BackgroundWorker.";
    }
    #region Windows Form Designer generated code
    private void InitializeComponent()
    {
    this.textBox1 = new System.Windows.Forms.TextBox();
    this.setTextUnsafeBtn = new System.Windows.Forms.Button();
    this.setTextSafeBtn = new System.Windows.Forms.Button();
    this.setTextBackgroundWorkerBtn = new System.Windows.Forms.Button();
    this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
    this.SuspendLayout();
    //
    // textBox1
    //
    this.textBox1.Location = new System.Drawing.Point(12, 12);
    this.textBox1.Name = "textBox1";
    this.textBox1.Size = new System.Drawing.Size(240, 20);
    this.textBox1.TabIndex = 0;
    //
    // setTextUnsafeBtn
    //
    this.setTextUnsafeBtn.Location = new System.Drawing.Point(15, 55);
    this.setTextUnsafeBtn.Name = "setTextUnsafeBtn";
    this.setTextUnsafeBtn.TabIndex = 1;
    this.setTextUnsafeBtn.Text = "Unsafe Call";
    this.setTextUnsafeBtn.Click += new System.EventHandler(this.setTextUnsafeBtn_Click);
    //
    // setTextSafeBtn
    //
    this.setTextSafeBtn.Location = new System.Drawing.Point(96, 55);
    this.setTextSafeBtn.Name = "setTextSafeBtn";
    this.setTextSafeBtn.TabIndex = 2;
    this.setTextSafeBtn.Text = "Safe Call";
    this.setTextSafeBtn.Click += new System.EventHandler(this.setTextSafeBtn_Click);
    //
    // setTextBackgroundWorkerBtn
    //
    this.setTextBackgroundWorkerBtn.Location = new System.Drawing.Point(177, 55);
    this.setTextBackgroundWorkerBtn.Name = "setTextBackgroundWorkerBtn";
    this.setTextBackgroundWorkerBtn.TabIndex = 3;
    this.setTextBackgroundWorkerBtn.Text = "Safe BW Call";
    this.setTextBackgroundWorkerBtn.Click +=
       new System.EventHandler(this.setTextBackgroundWorkerBtn_Click);
    // backgroundWorker1
    //
    this.backgroundWorker1.RunWorkerCompleted +=
        new System.ComponentModel.RunWorkerCompletedEventHandler(
          this.backgroundWorker1_RunWorkerCompleted);
    //Form1
    this.ClientSize = new System.Drawing.Size(268, 96);
    this.Controls.Add(this.setTextBackgroundWorkerBtn);
    this.Controls.Add(this.setTextSafeBtn);
    this.Controls.Add(this.setTextUnsafeBtn);
    this.Controls.Add(this.textBox1);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false);
    this.PerformLayout();
    }
    #endregion
    [STAThread]
    static void Main()
    {
    Application.EnableVisualStyles();
    Application.Run(new Form1());
    }
    }
    }


  • 相关阅读:
    UE4 WCF RestFul 服务器 读取JSON 数据并解析 简单实例
    Android aidl Binder框架浅析
    AIDL
    android 五种存储方式
    Android进程间通信机制
    Service全面总结
    Android平台中关于音频播放
    Android广播机制
    Cursor,CursorAdapter中的观察者模式解析
    ContentProvider和Uri详解
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2033196.html
Copyright © 2011-2022 走看看