如何将 WaitAll() 转换为异步和等待
How to convert WaitAll() to async and await
是否可以使用 async await 语法重写下面的代码?
private void PullTablePages()
{
var taskList = new List<Task>();
var faultedList = new List<Task>();
foreach (var featureItem in featuresWithDataName)
{
var task = Task.Run(() => PullTablePage();
taskList.Add(task);
if(taskList.Count == Constants.THREADS)
{
var index = Task.WaitAny(taskList.ToArray());
taskList.Remove(taskList[index]);
}
}
if (taskList.Any())
{
Task.WaitAll(taskList.ToArray());
}
//todo: do something with faulted list
}
当我如下重写它时,代码不会阻塞并且控制台应用程序在大多数线程完成之前完成。
似乎 await 语法没有像我预期的那样阻塞。
private async void PullTablePagesAsync()
{
var taskList = new List<Task>();
var faultedList = new List<Task>();
foreach (var featureItem in featuresWithDataName)
{
var task = Task.Run(() => PullTablePage();
taskList.Add(task);
if(taskList.Count == Constants.THREADS)
{
var anyFinished = await Task.WhenAny(taskList.ToArray());
await anyFinished;
for (var index = taskList.Count - 1; index >= 0; index--)
{
if (taskList[index].IsCompleted)
{
taskList.Remove(taskList[index]);
}
}
}
}
if (taskList.Any())
{
await Task.WhenAll(taskList);
}
//todo: what to do with faulted list?
}
可以吗?
WaitAll 似乎并不等待所有任务完成。我如何让它这样做? return 类型表示它 return 是一项任务,但似乎无法弄清楚语法。## 标题 ##
刚接触多线程,请见谅
Is it possible to rewrite the code below using the async await syntax?
是也不是。是的,因为你已经做到了。不,因为虽然从函数 实现 的角度来看是等价的,但从函数 调用者 的角度来看是不等价的(正如您已经体验过的控制台应用程序) .与许多其他 C# 关键字相反,await
不是语法糖。编译器强制你用 async
标记你的函数以启用 await
构造是有原因的,原因是现在你的函数不再阻塞并且给调用者增加了额外的责任- 要么将自己设置为非阻塞 (async
),要么对您的函数使用阻塞调用。每个 async
方法实际上是并且应该 return Task
或 Task<TResult>
然后编译器将警告忽略该事实的调用者。唯一的例外是 async void
,它应该 仅 用于事件处理程序,本质上不应该关心被通知的对象在做什么。
简而言之,async/await
不是为了重写同步(阻塞代码),而是为了方便将其转为异步(非阻塞)。如果您的函数应该是同步的,那么只需保持原样(并且您的原始实现完美地做到了这一点)。但是如果你需要异步版本,那么你应该把签名改成
private async Task PullTablePagesAsync()
使用 await
重写的正文(您已经正确完成了)。为了向后兼容,使用像这样的新实现提供旧的同步版本
private void PullTablePages() { PullTablePagesAsync().Wait(); }
It seems like the await syntax doesn't block as I expected.
你期待错了。
await
语法不应该阻塞 - 只是执行流程在任务完成之前不应该继续。
通常您在 return 任务的方法中使用 async/await。在您的情况下,您在 return 类型为 void 的方法中使用它。
了解 async void 方法需要花费时间,这就是通常不鼓励使用它们的原因。异步无效方法 运行 与调用方法同步(阻塞),直到等待第一个(未完成)任务。之后发生的事情取决于执行上下文(通常你 运行ning 在池中)。重要事项:调用方法(调用 PullTablePAgesAsync
的方法)不知道延续,也不知道 PullTablePagesAsync
中的所有代码何时完成。
也许看看 async/await 最佳实践 MSDN
是否可以使用 async await 语法重写下面的代码?
private void PullTablePages()
{
var taskList = new List<Task>();
var faultedList = new List<Task>();
foreach (var featureItem in featuresWithDataName)
{
var task = Task.Run(() => PullTablePage();
taskList.Add(task);
if(taskList.Count == Constants.THREADS)
{
var index = Task.WaitAny(taskList.ToArray());
taskList.Remove(taskList[index]);
}
}
if (taskList.Any())
{
Task.WaitAll(taskList.ToArray());
}
//todo: do something with faulted list
}
当我如下重写它时,代码不会阻塞并且控制台应用程序在大多数线程完成之前完成。
似乎 await 语法没有像我预期的那样阻塞。
private async void PullTablePagesAsync()
{
var taskList = new List<Task>();
var faultedList = new List<Task>();
foreach (var featureItem in featuresWithDataName)
{
var task = Task.Run(() => PullTablePage();
taskList.Add(task);
if(taskList.Count == Constants.THREADS)
{
var anyFinished = await Task.WhenAny(taskList.ToArray());
await anyFinished;
for (var index = taskList.Count - 1; index >= 0; index--)
{
if (taskList[index].IsCompleted)
{
taskList.Remove(taskList[index]);
}
}
}
}
if (taskList.Any())
{
await Task.WhenAll(taskList);
}
//todo: what to do with faulted list?
}
可以吗?
WaitAll 似乎并不等待所有任务完成。我如何让它这样做? return 类型表示它 return 是一项任务,但似乎无法弄清楚语法。## 标题 ##
刚接触多线程,请见谅
Is it possible to rewrite the code below using the async await syntax?
是也不是。是的,因为你已经做到了。不,因为虽然从函数 实现 的角度来看是等价的,但从函数 调用者 的角度来看是不等价的(正如您已经体验过的控制台应用程序) .与许多其他 C# 关键字相反,await
不是语法糖。编译器强制你用 async
标记你的函数以启用 await
构造是有原因的,原因是现在你的函数不再阻塞并且给调用者增加了额外的责任- 要么将自己设置为非阻塞 (async
),要么对您的函数使用阻塞调用。每个 async
方法实际上是并且应该 return Task
或 Task<TResult>
然后编译器将警告忽略该事实的调用者。唯一的例外是 async void
,它应该 仅 用于事件处理程序,本质上不应该关心被通知的对象在做什么。
简而言之,async/await
不是为了重写同步(阻塞代码),而是为了方便将其转为异步(非阻塞)。如果您的函数应该是同步的,那么只需保持原样(并且您的原始实现完美地做到了这一点)。但是如果你需要异步版本,那么你应该把签名改成
private async Task PullTablePagesAsync()
使用 await
重写的正文(您已经正确完成了)。为了向后兼容,使用像这样的新实现提供旧的同步版本
private void PullTablePages() { PullTablePagesAsync().Wait(); }
It seems like the await syntax doesn't block as I expected.
你期待错了。
await
语法不应该阻塞 - 只是执行流程在任务完成之前不应该继续。
通常您在 return 任务的方法中使用 async/await。在您的情况下,您在 return 类型为 void 的方法中使用它。
了解 async void 方法需要花费时间,这就是通常不鼓励使用它们的原因。异步无效方法 运行 与调用方法同步(阻塞),直到等待第一个(未完成)任务。之后发生的事情取决于执行上下文(通常你 运行ning 在池中)。重要事项:调用方法(调用 PullTablePAgesAsync
的方法)不知道延续,也不知道 PullTablePagesAsync
中的所有代码何时完成。
也许看看 async/await 最佳实践 MSDN