【发布时间】:2017-07-13 02:16:17
【问题描述】:
我认为这与我非常糟糕的异步编程有关。
来了。我正在使用异步方法获取 mailchimp 订阅者,但结果只是挂起并且永远不会返回到主线程。
异步方法
public async Task<List<Subscriber>> GetMailChimpSubscribers()
{
TaskCompletionSource<List<Subscriber>> result = new TaskCompletionSource<List<Subscriber>>();
await Task.Run(async () =>
{
var subscribers = new List<Subscriber>();
var listId = "";
var members = await _manager.Members.GetAllAsync(listId);
foreach (var item in members)
{
var sub = new Subscriber();
sub.Email = item.EmailAddress;
subscribers.Add(sub);
}
result.SetResult(subscribers);
});
return result.Task.Result;
}
这在 result.SetResult(subscribers) 语句之后完全挂起。
这是从
调用的public static List<Subscriber> GetSubscribers()
{
MailchimpHelper helper = new MailchimpHelper();
var subscribers= helper.GetMailChimpSubscribers();
return subscribers.Result;
}
这里到底出了什么问题?设置错了吗?
PS:mailchimp 或 api 没有问题,它在控制台中运行良好。这对于异步编程来说纯粹是一件坏事
更新:
如果有人遇到这种情况。该博客帮助清除了很多
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
以下答案和博客中的工作解决方案。
public async Task<List<Subscriber>> GetMailChimpSubscribers()
{
var subscribers = new List<Subscriber>();
var listId = "";
var members =
await _manager.Members.GetAllAsync(listId).**ConfigureAwait(false)**;
foreach (var item in members)
{
var sub = new Subscriber();
sub.Email = item.EmailAddress;
subscribers.Add(sub);
}
return subscribers;
}
public static List<Subscriber> GetSubscribers()
{
MailchimpHelper helper = new MailchimpHelper();
var subscribers= helper.GetMailChimpSubscribers();
subscribers.Wait();
return subscribers.Result;
}
【问题讨论】:
-
您的
GetSubscribers()方法也必须是async,并且您必须await调用helper.GetMailChimpSubscribers()而不是调用.Result。 -
另外,在
await Task.Run(async () =>中包装一个已经异步的调用是没有用的。 -
@PeterBons,严格来说这不是真的,因为 Task.Run 将安排异步匿名方法在后台线程中运行。不使用时,该方法将在调用线程上执行,这可能是 UI 线程。
-
为清楚起见,您能否标记(或指定)您正在使用的环境(ASP.net、WPF 等)? (只是明确说明是否存在同步上下文以及是否可以使用
async“一直向下”)。 -
关于编辑:由于缺少同步上下文,我希望这可以在控制台应用程序中工作。它“宣传不佳”,但异步在控制台应用程序中的工作方式与它在具有同步上下文的环境中的工作方式大不相同。
标签: c# asp.net-mvc async-await