异步 - 等待进度条和交叉线程问题

Rin*_*gil 2 c# async-await

我一直在使用异步的进度条并在C#中等待.我Form1.cs使用以下代码制作了一个简单的表单:

public partial class Form1 : Form
{
    private Progress<TaskAsyncExProgress> progress;
    public Form1(Progress<TaskAsyncExProgress> progress = null)
    {
        InitializeComponent();
        if (progress == null)
        {
            this.progress = new Progress<TaskAsyncExProgress>();
        }
        else
        {
            this.progress = progress;
        }

        this.progress.ProgressChanged += (s, e) =>
        {
            Debug.WriteLine("Progress: " + e.ProgressPercentage + "%");

            progressBar.Value += e.ProgressPercentage;

            txtResult.Text += e.Text;
        };

        Shown += async (s, e) =>
        {
            try
            {
                await Task.Run(() => HardTask(progress));
                txtResult.Text += "Done!";
            }
            finally
            {
                MessageBox.Show("Done!");
                Close();
            }
        };
    }

    void HardTask(Progress<TaskAsyncExProgress> progress)
    {
        incrementProgress();
        Thread.Sleep(5000);
    }
    public void incrementProgress()
    {
        Task.Run(() =>
        {
            for (int i = 0; i < 100; i++)
            {
                var args = new TaskAsyncExProgress();
                args.ProgressPercentage = 1;
                args.Text = i.ToString() + " "; 
                ((IProgress<TaskAsyncExProgress>)progress).Report(args);
                Thread.Sleep(10);
            }
        }
        );
    }
}


public class TaskAsyncExProgress
{
    public int ProgressPercentage { get; set; }

    public string Text { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在我看来Program.cs,我有两个案例:

// Case 1: This causes a cross-thread issue
//Progress<TaskAsyncExProgress> progress = new Progress<TaskAsyncExProgress>();
//Form1 frm =  new Form1(progress);

// Case 2: This works fine
Form1 frm =  new Form1();

frm.ShowDialog();
Run Code Online (Sandbox Code Playgroud)

为什么案例1会导致跨线程问题,但案例2工作正常?如果你想Report在表单本身之外使用方法,我觉得Case 1可能是一个非常有用的构造.

编辑:我知道我可以使用BeginInvoke或类似的,但我的印象是Async + Await应该这样做,以便我不再需要这样做了.

Ser*_*rvy 8

Progress类可捕获的值SynchronizationContext.Current在创建时它,并使用(或默认的同步方面,如果没有价值)发布的进展改变了事件处理程序.

在第一个示例中,您将在创建Progress同步上下文之前创建实例.在第二个示例中,您在创建同步上下文创建它,这就是它工作的原因.