You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

异步并发方法运行问题求助:WinForms按钮与任务同步实现

WinForms并行任务与Async/Await实现方案

需求说明

  • 点击Start按钮后,文本切换为Stop
  • 类中两个方法并发运行
  • 窗体等待并发方法执行完成
  • 执行完成后,按钮文本变回Start
  • Label5显示"completed"

修改后的代码

Form1.cs

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

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

        private async void Button1_Click(object sender, EventArgs e)
        {
            label8.Text = Environment.CurrentManagedThreadId.ToString();
            Button1.Text = "Stop";
            label5.Text = "";
            Button1.Enabled = false;

            try
            {
                await StartAllCountingAsync();
            }
            finally
            {
                label5.Text = "Completed.";
                Button1.Text = "Start";
                Button1.Enabled = true;
            }
        }

        private async Task StartAllCountingAsync()
        {
            await Task.WhenAll(
                AsyncClass1.StartCount1Async(label3, label6),
                AsyncClass1.StartCount2Async(label4, label7)
            );
        }
    }
}

AsyncClass1.cs

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

namespace TestingTaskAsync
{
    internal class AsyncClass1
    {
        public static async Task StartCount1Async(Label label3, Label label6)
        {
            label6.Text = $"Thread: {Environment.CurrentManagedThreadId}";
            
            await Task.Run(() =>
            {
                for (int xI = 0; xI < 100000; xI++)
                {
                    label3.Invoke((MethodInvoker)(() => label3.Text = $"Reached: {xI}"));
                }
            });
        }

        public static async Task StartCount2Async(Label label4, Label label7)
        {
            label7.Text = $"Thread: {Environment.CurrentManagedThreadId}";
            
            await Task.Run(() =>
            {
                for (int xI = 0; xI < 100000; xI++)
                {
                    label4.Invoke((MethodInvoker)(() => label4.Text = $"Reached: {xI}"));
                }
            });
        }
    }
}

关键修改说明

  1. 按钮事件改为async void:WinForms事件处理方法支持async void,使用await不会阻塞UI线程,确保按钮文本能及时切换为Stop。
  2. 用Task.WhenAll替代Parallel.Invoke:Parallel.Invoke是同步阻塞调用,会导致UI卡死;Task.WhenAll异步等待多任务完成,保持界面响应。
  3. 后台任务用Task.Run包装:把循环计算逻辑放到ThreadPool线程执行,避免占用UI线程引发卡顿。
  4. 禁用按钮防止重复触发:任务执行期间禁用按钮,避免重复点击,完成后恢复可用状态。
  5. 遵循async/await规范:将原同步方法改为返回Task的异步方法,确保能被正确等待。

优化建议:频繁调用Invoke更新UI会加重界面负担,实际项目可改为每隔N次循环更新一次,比如:

for (int xI = 0; xI < 100000; xI++)
{
    if (xI % 100 == 0)
    {
        label3.Invoke((MethodInvoker)(() => label3.Text = $"Reached: {xI}"));
    }
}

内容的提问来源于stack exchange,提问作者Sdx.1969

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 20:00:02