task为什么等待task ?在执行下一段代码之前运行,但不用于Task.Factory.StartNew
本文关键字:task 运行 StartNew Factory Task 用于 代码 一段 等待 为什么 执行 | 更新日期: 2023-09-27 18:19:02
至少在我的代码中实现它时,我必须修改StartNew Task以获得相同的行为。在我的视图中有一个开始按钮。它的IsEnabled属性在视图模型中被绑定到一个布尔值。如果不添加await task.ContinueWith(_ => true);
并将return true;
移出try块,PopulateListStartNew Task不会等待,因此按钮保持启用状态。我更喜欢使用Task.Factory.StartNew
,因为传递TaskScheduler使代码更具可读性(没有Dispatcher混乱)。Records是一个ObservableCollection
我认为任务。运行基本上是一个快捷方式(每个任务)。Run vs Task.Factory.StartNew。无论如何,我想更好地理解行为上的差异,并且非常感谢任何有关使我的示例代码更好的建议。
public async Task<bool> PopulateListTaskRun(CancellationToken cancellationToken)
{
try
{
await Task.Run(async () =>
{
// Clear the records out first, if any
Application.Current.Dispatcher.InvokeAsync(() => Records.Clear());
for (var i = 0; i < 10; i++)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
// Resharper says do this to avoid "Access to modified closure"
var i1 = i;
Application.Current.Dispatcher.InvokeAsync(() =>
{
Records.Add(new Model
{
Name = NamesList[i1],
Number = i1
});
Status = "cur: " +
i1.ToString(
CultureInfo.InvariantCulture);
});
// Artificial delay so we can see what's going on
await Task.Delay(200);
}
Records[0].Name = "Yes!";
}, cancellationToken);
return true;
}
catch (Exception)
{
return false;
}
}
public async Task<bool> PopulateListStartNew(CancellationToken cancellationToken, TaskScheduler taskScheduler)
{
try
{
var task = await Task.Factory.StartNew(async () =>
{
// Clear the records out first, if any
Records.Clear();
for (var i = 0; i < 10; i++)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
Records.Add(new Model
{
Name = NamesList[i],
Number = i
});
Status = "cur: " +
i.ToString(
CultureInfo.InvariantCulture);
// Artificial delay so we can see what's going on
await Task.Delay(200);
}
Records[0].Name = "Yes!";
}, cancellationToken, TaskCreationOptions.None, taskScheduler);
// Had to add this
await task.ContinueWith(_ => true);
}
catch (Exception)
{
return false;
}
// Had to move this out of try block
return true;
}
您在问题中发布的链接有答案:Task.Run
理解并解开async Task
委托,而StartNew
返回Task<Task>
,您必须通过调用Unwrap
或执行双await
来解开自己。
但是,我建议您完全重写代码,如下所示。注:
- 不要使用
Dispatcher
。对于正确编写的async
代码,不应该需要它。 将所有后台工作方法和异步操作视为UI线程的"服务"。因此,你的方法将根据需要周期性地返回到UI上下文。
:
public async Task<bool> PopulateListTaskRunAsync(CancellationToken cancellationToken)
{
try
{
// Clear the records out first, if any
Records.Clear();
for (var i = 0; i < 10; i++)
{
cancellationToken.ThrowIfCancellationRequested();
Records.Add(new Model
{
Name = NamesList[i],
Number = i
});
Status = "cur: " + i.ToString(CultureInfo.InvariantCulture);
// Artificial delay so we can see what's going on
await Task.Delay(200);
}
Records[0].Name = "Yes!";
return true;
}
catch (Exception)
{
return false;
}
}
我对这些管道太不舒服了,但我会试着回答。
第一个为什么你的第二个代码不工作:
-
你给StartNew一个异步委托类似于Func
所以StartNew将返回一个Task 你等待外部任务立即结束,因为它包含返回内部任务(不太确定) -
然后你等待内部任务的延续,内部线程的执行,你打算做什么;但我想,如果你直接等待内部任务本身,它应该是一样的:
await await Task.Factory.StartNew(async ...
为什么你的第一个代码工作:
-
根据MSDN文档任务。Run直接返回一个Task对象,我猜内部任务
-
所以你直接等待内部任务,而不是中间任务,所以它只是按预期工作
至少这是我的理解,记住我还没有玩过所有这些东西(没有VS 2012)。:)