相关疑难解决方法(0)

在ASP.NET的上下文中,为什么不调用异步方法时Task.Run(...).结果死锁?

我用一个控制器和一个方法创建了一个简单的WebApi项目:

public static class DoIt
{
    public static async Task<string> GetStrAsync(Uri uri)
    {
        using (var client = new HttpClient())
        {
            var str = await client.GetStringAsync(uri);
            return str;
        }
    }
}

public class TaskRunResultController : ApiController
{
    public string Get()
    {
        var task = Task.Run(() =>
            DoIt.GetStrAsync(new Uri("http://google.com"))
        );
        var result = task.Result;

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

我非常了解async/await和tasks; 斯蒂芬克莱里几乎虔诚地跟随他.只是存在.Result让我焦虑,我希望这会陷入僵局.我知道这Task.Run(...)很浪费,导致在等待异步DoIt()完成时占用一个线程.

问题是这不是死锁,而是让我心悸.

我看到一些答案,如/sf/answers/2282496401/,我也观察到SynchronizationContext.Currentlambda执行时为null.但是,我也有类似的问题,问为什么上面的代码会出现死锁,而且我发现死锁ConfigureAwait(false)是在使用(不捕获上下文)的情况下发生的.Result.

是什么赋予了?

c# asp.net asynchronous task synchronizationcontext

5
推荐指数
1
解决办法
1064
查看次数

许多等待Async方法,或者单个等待包装Task.Run?

假设我们必须通过异步流向数据库写下1000个元素的列表.是等待1000次异步插入语句,还是将所有1000个插入包装在一个封装到Task.Run语句中的单个同步方法中等待一次?

例如,SqlCommand每个方法都加上他的async版本.在这种情况下,我们有一个insert语句,所以我们可以调用ExecuteNonQueryExecuteNonQueryAsync.

通常,在异步/等待指南上,我们读到如果您有某个方法可用的异步版本,则应该使用它.所以我们写一下:

async Task Save(IEnumerable<Savable> savables)
{
    foreach(var savable in savables)
    {
        //create SqlCommand somehow
        var sqlCmd = CreateSqlCommand(savable);

        //use asynchronous version
        await sqlCmd.ExecuteNonQueryAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码很清楚.但是,每次从await部分出来时,它也会在UI线程上返回,然后在遇到的下一个await中返回后台线程,依此类推(不是吗?).这意味着用户可以看到一些延迟,因为UI线程不断地被继续await执行下一个foreach周期而中断,并且在那段时间内UI冻结了一点.

我想知道我是否更好地编写这样的代码:

async Task Save(IEnumerable<Savable> savables)
{
    await Task.Run(() =>
    {
        foreach(var savable in savables)
        {
            //create SqlCommand somehow
            var sqlCmd = CreateSqlCommand(savable);

            //use synchronous version
            sqlCmd.ExecuteNonQuery();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

以这种方式,整个foreach在辅助线程上执行,而在UI线程和辅助线程之间没有连续切换.这意味着UI线程可以在整个持续时间内foreach(例如微调器或进度条)自由更新View ,也就是说,用户不会感知到任何延迟.

我对吗?或者我错过了一些关于"异步一直向下"的事情?

我不是在寻找简单的基于意见的答案,我正在寻找async/await指南的解释,以及解决它的最佳方法.

编辑: …

c# async-await c#-5.0

2
推荐指数
1
解决办法
806
查看次数

异步库调用互相依赖以及如何处理?

这是我之前发布的一个问题的后续问题.使用Task.Run调用异步方法似乎错了?

我认为承包商编写的代码是错误的,但是从提供的答案开始,我现在想知道这是否是图书馆的错误.该库公开了我需要使用的两种方法.一个返回一个"模板",一个消耗该模板的一部分(无论如何它都在我的实现中).但两者都是async返回的方法Tasks.

解释我的库有方法:

public Task<TemplateInfo> TemplateInfo(TemplateInfoRequest request);
public Task<List<EmailResult>> SendMessageTemplate(SendMessageTemplateRequest request);
Run Code Online (Sandbox Code Playgroud)

我需要这样称呼它们:

public bool SendMessage()
{
  var template = TemplateInfo(...);
  var message = //use template to create message
  var sendResponse = SendMessageTemplate(message);

   return sendResponse.Count > 0;
}
Run Code Online (Sandbox Code Playgroud)

所以第二次通话依赖于第一次.这是异步对我没有意义的地方.我不能也不想并行运行这些.我想按顺序运行它们.我希望我的方法是同步的.

我之前的问题中答案还指出:

由于您在异步方法上阻塞(您不应该这样做),因此您可能会陷入僵局.

那么如何async以这样的方式访问这些方法,即依次处理它们并返回同步结果但不会导致死锁?

c# asp.net asynchronous task-parallel-library async-await

1
推荐指数
1
解决办法
161
查看次数