`
498320858
  • 浏览: 393124 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

c# winform编程之多线程ui界面资源修改总结篇

    博客分类:
  • c#
阅读更多
单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么做,比如:
private void btnSet_Click(object sender, EventArgs e)
{   
    Thread t = new Thread(new ParameterizedThreadStart(SetTextBoxValue));
    //当然也可以用匿名委托写成Thread t = new Thread(SetTextBoxValue);
    t.Start("Hello World");
}


void SetTextBoxValue(object obj)
{
    this.textBox1.Text = obj.ToString();
}

运行时,会报出一个无情的错误:
线程间操作无效: 从不是创建控件“textBox1”的线程访问它。

究其原因,winform中的UI控件不是线程安全的,如果可以随意在任何线程中改变其值,你创建一个线程,我创建一个线程,大家都来抢着更改"TextBox1"的值,没有任何秩序的话,天下大乱...

解决办法:
1.掩耳盗铃法(Control.CheckForIllegalCrossThreadCalls = false;)--仅Winform有效
using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
    public partial class Form1 : Form
    {       

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;//这一行是关键     
        }
      

        private void btnSet_Click(object sender, EventArgs e)
        {          
            Thread t = new Thread(new ParameterizedThreadStart(SetTextBoxValue));
            t.Start("Hello World");
        }


        void SetTextBoxValue(object obj)
        {
            this.textBox1.Text = obj.ToString();
        }       
    }
}

设置Control.CheckForIllegalCrossThreadCalls为false,相当于不检测线程之间的冲突,允许各路线程随便乱搞,当然最终TextBox1的值到底是啥难以预料,只有天知道,不过这也是最省力的办法

2.利用委托调用--最常见的办法(仅WinForm有效)
using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        delegate void D(object obj);

        public Form1()
        {
            InitializeComponent();           
        }
      

        private void btnSet_Click(object sender, EventArgs e)
        {          
            Thread t = new Thread(new ParameterizedThreadStart(SetTextBoxValue));
            t.Start("Hello World");
        }


        void SetTextBoxValue(object obj)
        {
            if (textBox1.InvokeRequired)
            {
                D d = new D(DelegateSetValue);
                textBox1.Invoke(d,obj);

            }
            else
            {
                this.textBox1.Text = obj.ToString();
            }
        }


        void DelegateSetValue(object obj)
        {
            this.textBox1.Text = obj.ToString();
        }
    }
}

3.利用SynchronizationContext上下文 -- 最神秘的方法(Winform/Silverlight能用)

之所以说它神秘,是因为msdn官方对它的解释据说也是不清不楚
using System;
using System.Threading;
using System.Windows.Forms;

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();           
        }      

        private void btnSet_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Run));
            MyPram _p = new MyPram() { context = SynchronizationContext.Current, parm = "Hello World" };
            t.Start(_p);
        }

        void Run(object obj)
        {
            MyPram p = obj as MyPram;
            p.context.Post(SetTextValue, p.parm);
        }


        void SetTextValue(object obj)
        {
            this.textBox1.Text = obj.ToString();
        }
    }


    public class MyPram
    {
        public SynchronizationContext context { set; get; }
        public object parm { set; get; }
    }
}

4.利用BackgroundWorker --最偷懒的办法(Winform/Silverlight通用)

BackgroundWorker会在主线程之外,另开一个后台线程,我们可以把一些处理放在后台线程中处理,完成之后,后台线程会把结果传递给主线程,同时结束自己。
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();           
        }      

        private void btnSet_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
            using (BackgroundWorker bw = new BackgroundWorker())
            {
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.RunWorkerAsync("Hello World");
            }
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
            e.Result = e.Argument;//这里只是简单的把参数当做结果返回,当然您也可以在这里做复杂的处理后,再返回自己想要的结果(这里的操作是在另一个线程上完成的)
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了
            this.textBox1.Text = e.Result.ToString();
            //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
        }      
    }   
}

5.Dispatcher.BeginInvoke--Silverlight的独门秘籍
代码
using System.Threading;
using System.Windows.Controls;
using System.Windows.Input;

namespace ThreadTest
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void LayoutRoot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Thread t = new Thread(SetTextValue);
            t.Start("Hello World");
        }

        void SetTextValue(object text)
        {
            this.Dispatcher.BeginInvoke(() => { this.txt.Text = text.ToString(); });           
        }
    }
}

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    WinForm C# 多线程编程并更新界面(UI)

    WinForm C# 多线程编程并更新界面(UI) 在 Windows 窗体应用程序中,多线程编程是非常重要的,这样可以提高应用程序的响应速度和用户体验。下面我们来讨论如何在 WinForm 中使用 C# 实现多线程编程并更新界面(UI...

    C#-WinForm跨线程修改UI界面的实例

    总结来说,C# WinForm应用中的跨线程修改UI是通过异步编程和UI线程同步机制来实现的。`Task`用于执行后台任务,`MethodInvoker`则帮助在主线程中安全地更新UI,确保程序的稳定性和正确性。这个实例提供了一个实用的...

    C#WinForm,多线程快速刷新界面。

    本文将深入探讨如何在C# WinForm中利用多线程实现界面快速刷新。 首先,我们需要理解Windows Forms(WinForm)应用程序的基础架构。默认情况下,WinForm应用程序有一个主线程,负责处理所有UI事件,如用户交互和...

    c#Winform异步线程刷新UI

    在C# WinForm应用开发中,我们经常遇到需要在后台执行耗时操作,同时保持用户界面(UI)的响应性。这就是异步编程的核心应用场景。VS2013支持.net框架4.0,该版本引入了Task类和异步编程模型,使得处理这种需求变得...

    C#WinForm跨线程更新UI的四种方法

    在C#编程中,开发Windows桌面应用程序时,我们经常遇到多线程操作,尤其是在WinForms应用中。当后台线程需要更新用户界面(UI)时,由于.NET Framework的安全机制,直接操作UI控件会引发“Cross-thread operation ...

    C# WinForm多线程防止界面假死源码

    本资源提供了"C# WinForm多线程防止界面假死"的源码示例,帮助初学者理解和实践如何在WinForm应用中正确使用多线程。 首先,理解WinForm中的主线程与工作线程的区别至关重要。主线程是负责更新和绘制UI的线程,而...

    C#winform高级设计(工控与界面).rar

    《C# WinForm高级设计(工控与界面)》是一个深入探讨C# Windows应用程序开发的资源集合,尤其关注WinForm技术在工控和用户界面设计中的应用。这个压缩包包含了丰富的学习材料,可以帮助开发者提升在C# WinForm平台...

    解决winform编程中使用线程界面卡死的案例

    总结起来,解决Winform界面卡死问题的关键在于理解和运用多线程以及委托。通过将耗时任务放到后台线程,并使用委托确保UI更新在主线程执行,可以有效避免界面卡死,提升用户体验。同时,理解.NET框架中的线程同步...

    C# Winform 多线程下载

    总的来说,C# Winform多线程下载的实现涉及到多线程编程、Winform UI交互以及HTTP文件下载,这些是开发高效桌面应用程序必备的基础技能。通过这样的实践,开发者能够提升处理并发任务的能力,优化用户体验,尤其是在...

    C# winform动态创建和关闭多线程源码 可运行

    在C#编程中,Windows Forms(Winform)应用程序经常需要处理多线程,以实现并发操作,提高程序的响应性和效率。本项目“C# Winform动态创建和关闭多线程源码 可运行”提供了一个完整的解决方案,适用于Visual Studio...

    c#多线程中子线程动态改变ui控件

    特别是在C#多线程编程中,子线程更新UI控件是一个常见的问题。本文将总结C#子线程更新UI控件的方法,介绍两种常用的方法,以便读者更好地理解和应用。 一、使用控件自身的Invoke/BeginInvoke方法 Control类实现了...

    WinForm后台线程与UI线程通讯

    在多线程编程中,主线程通常是创建UI并处理用户交互的线程,而后台线程则用于执行耗时任务。.NET Framework中的控件都是线程感知的,它们只能在其创建的线程(UI线程)中被修改,这就是所谓的线程亲和性。 为了实现...

    Winform实现多线程异步更新UI(进度及状态信息)

    本文将详细讲解如何在WinForm应用中实现多线程异步更新UI。 1. **线程基础知识**:在Windows操作系统中,每个应用程序都有一条主线程,负责创建和管理UI。其他线程称为工作线程,用于执行非UI相关的任务。主线程与...

    C# winform多线程模板示例,winform多线程例子,C#

    通过这个C# WinForm多线程模板示例,开发者可以学习到如何优雅地处理后台任务,保持UI响应,并理解多线程编程中的核心概念。同时,了解如何利用线程同步机制以及异步编程模型,能够更好地优化应用程序的性能和用户...

    C#Winform使用TCPListener加多线程编程实现客户端服务器端聊天模式

    总结来说,C# Winform利用TCPListener和TCPClient进行网络通信,结合多线程处理客户端和服务器端的数据交互,委托确保了在安全的上下文中更新UI,从而实现了一个完整的聊天模式。这个过程中,不仅学习了网络编程的...

    C#Winform异步多线程和线程池集成的用法

    在`WinformThreadApp3`项目中,这些概念被集成在一起,展示了如何在Winform应用中同时使用异步编程、多线程和线程池进行数据库操作和日志记录。通过对这些技术的合理应用,开发者可以创建出高效、响应性强的桌面应用...

    C#下WINFORM和WINCE多线程编程

    在C#编程环境中,开发Windows...总结,C#中的WinForm和WinCE多线程编程涉及创建线程、同步机制、UI更新、异常处理和性能优化等多个方面。通过深入理解这些概念和实践,开发者可以构建出高效、响应性的跨平台应用程序。

    C# winform 防止界面卡住 线程 委托

    在C# WinForm开发中,我们常常遇到这样一个问题:当执行耗时操作(如大量数据处理、网络请求等)时,界面会变得无响应,即“卡住”...在设计多线程应用时,还需注意线程安全、资源竞争等问题,以避免潜在的错误和异常。

    C#界面编程Winform,最详细demo!

    8. **多线程应用**:Winform支持多线程编程,可以创建新的线程执行耗时操作,避免阻塞UI线程,提升用户体验。 9. **设计时特性**:Visual Studio IDE提供了强大的Winform设计器,可以直接拖放控件,设置属性,预览...

Global site tag (gtag.js) - Google Analytics