只是为 c# 4.0 提供另一种解决方案。这类似于@Debora 和@Jay(好吧,如果您忘记了 while(true)... 只是在谈论 BeginInvoke)解决方案,但完全基于 TPL 并且更接近使用 async/ 生成的代码等待:
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(() =>
{
listBox1.Items.Add("Number cities in problem = " + i.ToString());
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
System.Threading.Thread.Sleep(1000);
}
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
您的工作任务应使用默认的 TaskScheduler(将使用 ThreadPool)进行调度,并在需要更新 UI 时使用 uiScheduler 回调到 UI 线程。请记住,这是一个示例实现,此示例可能存在一些问题,例如,内部任务计划在 UI 线程上执行,但调用任务并未等待,因此 sleep 将实际运行当内部任务正在运行时。不要等待任务也很重要,否则可能会出现死锁(内部任务试图在等待外部任务的 UI 线程上运行)。
我通常在延续任务上使用 uiScheduler 向 UI 提供数据。在你的情况下,它可能是这样的:
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
//load data or perform work on background thread
var itemList = new List<int>();
for (int i = 0; i < 10; i++)
{
itemList.Add(i);
System.Threading.Thread.Sleep(1000);
}
return itemList;
}).ContinueWith((itemList) =>
{
//get the data from the previous task a continue the execution on the UI thread
foreach(var item in itemList)
{
listBox1.Items.Add("Number cities in problem = " + item.ToString());
}
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
生成的编译代码将与使用 async/await 生成的代码非常相似(如果不相等)