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 更适用于复杂情况,当你希望保持当前线程的活跃,不关心执行顺序或能够处理潜在的并发问题时。 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fyhs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值