我遇到了一些意想不到的行为,我想对此有所了解。我创建了一个简单的例子来演示这个问题。我使用 调用异步函数Task.Run
,它将不断生成结果,并用于IProgress
向 UI 传递更新。但是我想等到 UI 实际更新后再继续,所以我尝试按照其他一些帖子中的建议使用 TaskCompletionSource(这似乎有点相似:Is it possible to await an event instead of another async method?.)我期待最初Task.Run
的等待,但正在发生的是内部发生的等待似乎将其向前移动,并且“END”发生在第一次迭代之后。Start()
是入口点:
public TaskCompletionSource<bool> tcs;
public async void Start()
{
var progressIndicator = new Progress<List<int>>(ReportProgress);
Debug.Write("BEGIN\r");
await Task.Run(() => this.StartDataPush(progressIndicator));
Debug.Write("END\r");
}
private void ReportProgress(List<int> obj)
{
foreach (int item in obj)
{
Debug.Write(item + " ");
}
Debug.Write("\r");
Thread.Sleep(500);
tcs.TrySetResult(true);
}
private async void StartDataPush(IProgress<List<int>> progressIndicator)
{
List<int> myList = new List<int>();
for (int i = 0; i < 3; i++)
{
tcs = new TaskCompletionSource<bool>();
myList.Add(i);
Debug.Write("Step " + i + "\r");
progressIndicator.Report(myList);
await this.tcs.Task;
}
}
有了这个,我得到:
BEGIN
Step 0
0
END
Step 1
0 1
Step 2
0 1 2
而不是我想要得到的是:
BEGIN
Step 0
0
Step 1
0 1
Step 2
0 1 2
END
我假设我对 Tasks 和 await 以及它们的工作方式有误解。我确实想StartDataPush
成为一个单独的线程,我的理解是它是。我的最终用途有点复杂,因为它涉及繁重的计算、更新到 WPF UI 以及发回通知它已完成的事件,但机制是相同的。我怎样才能实现我想要做的事情?