我一直在使用异步的进度条并在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应该这样做,以便我不再需要这样做了.
本Progress类可捕获的值SynchronizationContext.Current在创建时它,并使用(或默认的同步方面,如果没有价值)发布的进展改变了事件处理程序.
在第一个示例中,您将在创建Progress同步上下文之前创建实例.在第二个示例中,您在创建同步上下文后创建它,这就是它工作的原因.