C#多线程与跨线程访问界面控件的方法

下面是 C# 多线程与跨线程访问界面控件的方法完整攻略:

1. C# 多线程基础

在 C# 中,多线程的基本实现是通过 System.Threading 命名空间下的类来实现的。常用的类有:

  • Thread:表示一个单独的线程。
  • ThreadPool:表示一个线程池,它包含了多个预先创建的线程。
  • Task:表示一个异步操作。

下面展示一个创建并运行线程的示例代码:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Thread newThread = new Thread(Worker);
        newThread.Start();
        Console.ReadLine();
    }

    static void Worker()
    {
        Console.WriteLine("Thread started.");
        Thread.Sleep(1000);
        Console.WriteLine("Thread ended.");
    }
}

上述代码会创建一个新线程并在该线程中运行 Worker 方法。Worker 方法简单地等待 1 秒钟后输出一段文本。在主线程中,我们等待用户按下回车键后才结束程序运行。

2. 跨线程访问控件

由于 C# 中 UI 控件是运行在主线程中的,因此我们不能直接在非主线程中访问它们。如果我们在非主线程中提供了一些 UI 操作的代码,尝试去更新 UI 控件的状态,将会抛出异常。因此,我们需要使用跨线程访问控件的方法来避免这个问题。

有多种方法可以实现跨线程访问控件,在这里我们介绍两种常见的方法。

2.1 Control.Invoke

Control.Invoke 方法可以在 UI 线程队列中执行指定的委托。下面是一个例子:

using System;
using System.Threading;
using System.Windows.Forms;

class Program
{
    static Label label;
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Form form = new Form();

        label = new Label();
        label.Text = "Starting...";
        label.Dock = DockStyle.Fill;
        form.Controls.Add(label);

        Thread newThread = new Thread(Worker);
        newThread.Start();

        Application.Run(form);
    }

    static void Worker()
    {
        DoUiWork("Thread started.");

        Thread.Sleep(1000);

        DoUiWork("Thread ended.");
    }

    delegate void StringArgReturningVoidDelegate(string text);

    static void UpdateLabel(string text)
    {
        label.Text = text;
    }

    static void DoUiWork(string text)
    {
        if (label.InvokeRequired)
        {
            StringArgReturningVoidDelegate del = new StringArgReturningVoidDelegate(UpdateLabel);
            label.Invoke(del, new object[] { text });
        }
        else
        {
            UpdateLabel(text);
        }
    }
}

在上述例子中,我们将一个标签加入了窗口中。在 Worker 方法中,我们通过 DoUiWork 方法来更新 label 对象的 Text 属性。该方法首先检查是否在 UI 线程中,如果在 UI 线程中,它会直接执行 UpdateLabel 方法,否则会通过 Control.Invoke 方法在 UI 线程中执行 UpdateLabel。使用 Control.Invoke 的时候需要注意:如果 UI 线程已经被阻塞,则调用 Control.Invoke 会导致死锁。

2.2 Control.BeginInvoke

Control.BeginInvoke 方法可以使一个委托异步地在 UI 线程中执行。与 Control.Invoke 不同,Control.BeginInvoke 不会阻塞当前线程。

using System;
using System.Threading;
using System.Windows.Forms;

class Program
{
    static Label label;
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Form form = new Form();

        label = new Label();
        label.Text = "Starting...";
        label.Dock = DockStyle.Fill;
        form.Controls.Add(label);

        Thread newThread = new Thread(Worker);
        newThread.Start();

        Application.Run(form);
    }

    static void Worker()
    {
        DoUiWork("Thread started.");

        Thread.Sleep(1000);

        DoUiWork("Thread ended.");
    }

    delegate void StringArgReturningVoidDelegate(string text);

    static void UpdateLabel(string text)
    {
        label.Text = text;
    }

    static void DoUiWork(string text)
    {
        if (label.InvokeRequired)
        {
            StringArgReturningVoidDelegate del = new StringArgReturningVoidDelegate(UpdateLabel);
            label.BeginInvoke(del, new object[] { text });
        }
        else
        {
            UpdateLabel(text);
        }
    }
}

上述代码与前一个例子很相似,唯一的不同在于我们换用了 Control.BeginInvoke 方法来切换到 UI 线程。具体用法也基本相同,我们通过 DoUiWork 方法来更新 label 对象的 Text 属性,方法中首先检查是否在 UI 线程中。如果在 UI 线程中,它会直接执行 UpdateLabel 方法,否则会通过 Control.BeginInvoke 方法在 UI 线程中异步执行 UpdateLabel。注意:使用 Control.BeginInvoke 的时候,我们不知道委托什么时候会被执行,因此需要小心使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#多线程与跨线程访问界面控件的方法 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • C#中委托的基本概念介绍

    下面我将详细讲解” C#中委托的基本概念介绍”: 委托 委托(Delegate)是C#中一个非常重要的概念,被称为“对象安全的函数指针”。委托可以指向一个具有特定参数列表和返回类型的方法。将方法封装在一个委托中,就可以像调用方法一样调用委托。委托在多线程编程、事件处理等方面有着广泛的应用。 委托的定义 C#中委托类型的定义通常需要指定该委托所能绑定的方法签名…

    C# 2023年5月15日
    00
  • 不安装excel使用c#创建excel文件

    下面是不安装Excel使用C#创建Excel文件的完整攻略: 1. 基于Office Open XML格式的Excel文件创建 使用C#,我们可以使用Microsoft Office Open XML库来生成基于XML的Excel (.xlsx)文件。下面是一个示例代码: using System; using System.IO; using Docume…

    C# 2023年6月1日
    00
  • ASP 使用三层架构 asp中使用类

    ASP(Active Server Pages)是一种动态网页开发技术,而三层架构则是一种常用的软件架构,采用三层架构能够有效地将程序分层,分离不同的功能模块,使得程序更加易于维护和扩展。 使用三层架构可以将程序分为三个层次:表示层、业务逻辑层和数据访问层。 表示层 表示层主要负责与用户进行交互,呈现数据,通过HTML/CSS/JS等技术将网页呈现给用户。 …

    C# 2023年6月8日
    00
  • ASP.NET中application对象的使用介绍

    ASP.NET中的Application对象是在网站全局范围内保存的一个数据容器,可以通过Application对象在多个页面间传递数据。本文将介绍ASP.NET中Application对象的使用方法,包括创建并保存数据、访问数据、以及如何在多个页面之间传递数据等。 创建并保存数据 在ASP.NET网站中,可以通过以下代码创建一个Application对象以…

    C# 2023年5月31日
    00
  • c# 日历控件的实现

    C#日历控件的实现 在C#中,开发者可以使用日历控件来方便地选择日期。下面分享一下如何在C#中实现日历控件。 步骤一:引用命名空间 首先,在你的C#程序中引用 System.Windows.Forms 命名空间。 using System.Windows.Forms; 步骤二:创建日历控件 在你的C#程序中,实例化一个 MonthCalendar 控件。 M…

    C# 2023年6月1日
    00
  • ASP.NET Core MVC 从入门到精通之wwwroot和客户端库

    随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生,或其他想从事ASP.NET Core MVC 系统开发的人员。 经过前几篇文章的讲解,初步了解ASP.NET Core MVC项目创建,启…

    C# 2023年4月22日
    00
  • C#计算矩阵的逆矩阵方法实例分析

    C#计算矩阵的逆矩阵方法实例分析 什么是逆矩阵 在数学中,矩阵的逆矩阵是一种可逆矩阵,其乘积可以等于单位矩阵。这是矩阵论中的一个重要概念,非常有实际应用。因为有了逆矩阵,我们可以在计算中求积或求解线性方程组等问题时候,使用逆矩阵来简化计算。 在C# 中,计算逆矩阵的方法比较简单,我们可以通过一些第三方的工具,比如MathNet Numerics这个库。 安装…

    C# 2023年6月8日
    00
  • 解析C#中的常量及如何在C#编程中定义常量

    下面是详细的解析C#中的常量及如何在C#编程中定义常量的攻略。 什么是常量 常量是在程序执行期间无法修改其值的数据。在C#中,常量使用 const 关键字进行定义,一旦被定义,其值将不能被修改。 定义常量 常量定义的语法格式如下: const <数据类型> <常量名称> = <常量值>; 以下是两个使用 const 关键字…

    C# 2023年6月6日
    00
合作推广
合作推广
分享本页
返回顶部