C# - 异步编程和同步编程总结

在Windows Forms或WPF等桌面应用中,Invoke 和 BeginInvoke 是用来在创建控件的UI线程上安全地执行代码的关键方法,主要是为了处理多线程环境下的UI交互。

  • Invoke: 它是一个同步操作。当你调用 Invoke 时,当前线程会被阻塞,直到UI线程执行完传递给它的委托(Lambda表达式或Delegate实例)。这种方式适用于需要保证执行顺序且不介意短暂阻塞当前线程的情况。

  • BeginInvoke: 另一方面,BeginInvoke 是一个异步操作。它将操作添加到UI线程的消息队列中并立即返回,不会等待执行完成。因此,当前线程不会被阻塞,可以继续执行后续代码。但是,由于非阻塞特性,BeginInvoke 不保证操作的执行顺序,如果有多个调用,它们可能会按照不同的顺序执行。在性能敏感或无序执行不影响逻辑的情况下,应优先考虑使用 BeginInvoke

异步编程

1.说明

var result = await Task.Run(() =>
{
    
});

2.举例 

var result = await Task.Run(() =>
{
    // 更新textBox1
    if (this.textBox1.InvokeRequired)
    {
        this.textBox1.BeginInvoke(new Action(() =>
        {
            this.textBox1.Text = "成品仓-" + name1;
        }));
    }
    else
    {
        this.textBox1.Text = "成品仓-" + name1;
    }

    // 更新verticalProgressBar1
    if (this.verticalProgressBar1.InvokeRequired)
    {
        this.verticalProgressBar1.BeginInvoke(new Action(() =>
        {
            this.verticalProgressBar1.Value = Convert.ToInt32(progress);
        }));
    }
    else
    {
        this.verticalProgressBar1.Value = Convert.ToInt32(progress);
    }

    // 更新label1
    if (this.label1.InvokeRequired)
    {
        this.label1.BeginInvoke(new Action(() =>
        {
            this.label1.Text = Convert.ToInt32(progress) + "%";
        }));
    }
    else
    {
        this.label1.Text = Convert.ToInt32(progress) + "%";
    }

    // 更新dataGridView2 DataSource
    if (this.dataGridView2.InvokeRequired)
    {
        this.dataGridView2.BeginInvoke(new Action(() =>
        {
            this.dataGridView2.DataSource = datatable2;
        }));
    }
    else
    {
        this.dataGridView2.DataSource = datatable2;
    }
});
 3.异步编程出现的问题
1.System.InvalidOperationException:“线程间操作无效: 从不是创建控件“”的线程访问它。”
 this.textBox1.BeginInvoke(new Action(() =>
 {
       
 }));
2.System.InvalidOperationException:“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”
if (this.textBox1.InvokeRequired)
{
    
}
else
{
    
}

2.同步编程 

Invoke(new Action(() => ... )) 

举例 

 Invoke(new Action(() =>
 {
     // 清空文本框等UI元素
     ClearUiElements();
 }));

总结来说,Invoke 适合需要保证顺序和同步的简单场景,而 BeginInvoke 更适用于复杂情况,当你希望保持当前线程的活跃,不关心执行顺序或能够处理潜在的并发问题时。 

相关推荐

  1. C# - 异步编程同步编程总结

    2024-07-12 05:28:06       26 阅读
  2. c#异步编程

    2024-07-12 05:28:06       42 阅读
  3. C# 异步编程

    2024-07-12 05:28:06       36 阅读
  4. c# 学习笔记 - 异步编程

    2024-07-12 05:28:06       48 阅读
  5. C# 系统学习(异步编程

    2024-07-12 05:28:06       35 阅读
  6. C# 异步编程模式详解

    2024-07-12 05:28:06       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 05:28:06       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 05:28:06       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 05:28:06       58 阅读
  4. Python语言-面向对象

    2024-07-12 05:28:06       69 阅读

热门阅读

  1. 微服务中的 “服务发现机制” 简介

    2024-07-12 05:28:06       25 阅读
  2. Vuetify3 + Nuxt3:跳转详情

    2024-07-12 05:28:06       23 阅读
  3. Django ORM中ExpressionWrapper的用途

    2024-07-12 05:28:06       22 阅读
  4. 【算法】反转链表

    2024-07-12 05:28:06       27 阅读
  5. NoSQL之REDIS配置与优化

    2024-07-12 05:28:06       20 阅读
  6. 阿里云API安全2.0全新发布

    2024-07-12 05:28:06       24 阅读
  7. (三)大模型/人工智能/机器学习/深度学习/NLP

    2024-07-12 05:28:06       19 阅读
  8. 数据库常见问题(持续更新)

    2024-07-12 05:28:06       25 阅读
  9. DevSecOps在数字政府建设中的实践研究

    2024-07-12 05:28:06       25 阅读
  10. Flask 不同版本项目的终端命令运行方式

    2024-07-12 05:28:06       22 阅读