Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Task.whallcontinuewith死锁_C#_Xamarin_Async Await_Task_Deadlock - Fatal编程技术网

C# Task.whallcontinuewith死锁

C# Task.whallcontinuewith死锁,c#,xamarin,async-await,task,deadlock,C#,Xamarin,Async Await,Task,Deadlock,我在xamarin中开发我的移动应用程序,并发送x个请求以显示我的应用程序的主页 我的代码如下: var taskcoll = _mainArticlesAppService.GetWelcomeStartColl().ContinueWith(async (res) => { _applicationContext.Categories = res.Result.Categories; }); var ta

我在xamarin中开发我的移动应用程序,并发送x个请求以显示我的应用程序的主页

我的代码如下:

    var taskcoll = _mainArticlesAppService.GetWelcomeStartColl().ContinueWith(async (res) =>
        {
            _applicationContext.Categories = res.Result.Categories;
        });

        var taskheros = _mainArticlesAppService.GetWelcomeHerosProfileDto().ContinueWith((res) =>
        {
            _applicationContext.HerosProfileDto = res.Result;
            RaisePropertyChanged(() => HerosProfileDto);
        });

        List<Task> tasksInit = new List<Task>();

        tasksInit.Add(taskcoll);
        tasksInit.Add(taskheros);

        await Task.WhenAll(tasksInit).ConfigureAwait(false);
var taskcoll=\u main articlesappservice.GetWelcomeStartColl().ContinueWith(异步(res)=>
{
_applicationContext.Categories=res.Result.Categories;
});
var taskheros=\u main articlesappservice.GetWelcomeHerosProfileDto()。ContinueWith((res)=>
{
_applicationContext.HerosProfileDto=res.Result;
RaisePropertyChanged(()=>HerosProfileDto);
});
List tasksini=new List();
tasksini.Add(taskcoll);
tasksini.Add(taskheros);
wait Task.WhenAll(tasksini).configurewait(false);
当没有问题时,一切都很好,一切正常

然而,当请求无法连接到远程api服务器时,它会在我的代码中抛出ecxeption,然后死锁,我不能再做任何事情,我的屏幕被冻结

发生死锁的代码是:

 protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        int count = 0;

       using (var cts = new CancellationTokenSource(new TimeSpan(0, 0, 30)))
        {
            HttpResponseMessage response = null;
            try
            {
                
                 response = await base.SendAsync(request, cts.Token);
            }
            catch(Exception ex)
            {
               
                throw ex; // --> Deadlock
            }
            if (response.StatusCode == HttpStatusCode.Unauthorized &&
                HasBearerAuthorizationHeader(request))
            {
                return await HandleUnauthorizedResponse(request, response, cancellationToken);
            }

            return response;
        }
    }
protected override async Task sendaync(HttpRequestMessage请求,
取消令牌(取消令牌)
{
整数计数=0;
使用(var cts=new CancellationTokenSource(new TimeSpan(0,0,30)))
{
HttpResponseMessage响应=null;
尝试
{
response=wait base.sendaync(请求,cts.Token);
}
捕获(例外情况除外)
{
抛出ex;//-->死锁
}
如果(response.StatusCode==HttpStatusCode.Unauthorized&&
HasBeareAuthorizationHeader(请求))
{
返回等待处理授权响应(请求、响应、取消令牌);
}
返回响应;
}
}

不要将
async/await
与continuation混用,这会使代码变得不可预测

此外,如果没有延续,代码看起来会更好:

var taskcoll=\u main articlesappservice.GetWelcomeStartColl();//启动第一个请求
var taskheros=_mainArticlesAppService.GetWelcomeHerosProfileDto();//启动第二个请求
//两个请求都已在运行
_applicationContext.Categories=(等待taskcoll.Categories;//等待第一个请求
_applicationContext.HerosProfileDto=等待任务heros;//等待第二个
RaisePropertyChanged(()=>HerosProfileDto);
也试试这个

response=await base.sendaync(请求,cts.Token).ConfigureAwait(false);
对于
throw ex
确保在请求之外使用
try catch处理
异常。当您按原样重新显示
异常
并且不执行任何其他操作时,在
sendsync
的内部,您根本不需要
try catch


下面是一个抽象示例,其中包含多个异步调用,这些调用以不同的延迟返回数据。没有返回类型,但使用类型化操作进行回调。这种方法对于我来说是最准确的,能够在完成每个请求后尽快收到不同类型的数据

类程序
{
静态异步任务主(字符串[]args)
{
SomeController=新的SomeController();
等待控制器。LoadAllData();
Console.ReadKey();
}  
}
公共类控制器
{
私有FirstDataClass _firstProperty;
私有SecondDataClass\u secondProperty;
私人第三十类财产;
公共FirstDataClass FirstProperty
{
get=>\u firstProperty;
设置
{
_firstProperty=价值;
Console.WriteLine(“接收到的第一个数据”);
}
}
公共SecondDataClass SecondProperty
{
get=>\u secondProperty;
设置
{
_第二属性=值;
Console.WriteLine(“接收到的第二个数据”);
}
}
公共第三十类第三十财产
{
get=>\u第三个属性;
设置
{
_第三财产=价值;
Console.WriteLine(“接收到的第三个数据”);
}
}
公共异步任务LoadAllData()
{
列表任务=新列表();
添加(GetFirstData(data=>FirstProperty=data));
添加(GetSecondData(data=>SecondProperty=data));
Add(GetThirdData(data=>ThirdProperty=data));
Console.WriteLine(“启动的任务”);
等待任务。何时(任务);
}
专用异步任务GetFirstData(操作)
{
等待任务。延迟(1000);
操作(新的FirstDataClass());
}
专用异步任务GetSecondData(操作)
{
等待任务。延迟(300);
操作(新的SecondDataClass());
}
私有异步任务GetThirdData(操作)
{
等待任务。延迟(500);
行动(新的ThirdDataClass());
}
}
公共类FirstDataClass{}
公共类SecondDataClass{}
公共类ThirdDataClass{}
控制台输出

已启动任务
收到的第二个数据
收到的第三个数据
收到的第一批数据
如果您不想更改API调用方法,可以将此方法用于该方法的包装器,如:

专用异步任务GetSomeData(操作)
{
动作(等待某个动作);
}
或者一些通用的包装器

专用异步任务GetDataWrapper(Func方法,操作)
{
行动(等待法);
}

谢谢。我该把任务称为什么?什么时候?在任务英雄之后?如果我这样做,我将不得不等待所有任务完成后再显示结果。对的我做多个请求的目标是在请求完成后在我的手机屏幕上显示检索到的结果。即使其他的没有。@dalton5您也不需要
任务。当所有
在这里时,两个
wait
s都已内联。@dalton5为了不进行复杂的强制转换,所有请求都应该具有相同的返回类型。更新