本文介绍了Task.WhenAll没有等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我学习了如何使用异步函数控制台应用程序,但不能使Task.WhenAll等到所有任务都完成。有什么不对以下code?它的工作原理同步。谢谢你在前进。

 静态无效的主要(字串[] args)
{
    ...
    IncluiValores(...);
    ...
}静态异步无效IncluiValores(...)
{
    任务<名单,LT; INT>> RES1 = att.GetAIDBAPI(ATT);
    任务<名单,LT; INT>> RES2 = att.GetAIDBAPI(ATT2);    清单< INT> []解析度=等待Task.WhenAll(RES1,RES2);    ...
}

更新 - 函数定义:

 公共异步任务<名单,LT; INT>> GetAIDBAPI(属性属性)
    {        清单< INT>结果= NULL;        连接client0 =新的连接();
        HttpClient的客户= client0.OpenAPIConnection(attributes.User [0],attributes.Pwd,attributes.Server,attributes.Chave,attributes.Server2);
        HTT presponseMessage响应=等待client.PostAsJsonAsync(API /属性/ ID /散,属性);        如果(response.IsSuccessStatus code)
        {
            VAR内容=等待response.Content.ReadAsStringAsync();
            结果= JsonConvert.DeserializeObject<动态>(内容).ToObject<名单,LT; INT>>();
        }
        其他
        {
            VAR CONTENT =[{1}];
            VAR的结果= JsonConvert.DeserializeObject<动态>(内容);
            结果= result.ToObject<名单,LT; INT>>();
        }        返回结果;    }

更新2 - 单独的上下文

 静态无效的主要(字串[] args)
{
    AsyncContext.Run(()=> MainAsync(参数));
}静态异步无效MainAsync(字串[] args)
{
    等待IncluiValores(...);
}静态异步任务IncluiValores(...)
{
    任务<名单,LT; INT>> RES1 = att.GetAIDBAPI(ATT);
    任务<名单,LT; INT>> RES2 = att.GetAIDBAPI(ATT2);    清单< INT> []解析度=等待Task.WhenAll(RES1,RES2); //< - 这里的错误
    //集合被修改;枚举操作可能不会执行
    ...
}
//试图更改为下面code,但它不会等待。
静态异步任务IncluiValores(...)
{
    任务<名单,LT; INT>> RES1 = att.GetAIDBAPI(ATT);
    任务<名单,LT; INT>> RES2 = att.GetAIDBAPI(ATT2);    等待Task.WhenAll(RES1,RES2); //< - 没有错误,只是不等待。
    list.Add(res1.Result [0]);
}


解决方案

您所呼叫的异步无效方法,它本质上意味着你没办法的await ING的结果。每当你忽略等待,你打破了同步链。操作发生真正的异步,而不是重新同步通过的await 。控制被返回给调用者,而(在将来某个时候)操作恢复异步

记住,等待收益。这仅仅是一贯使用的等待,让你同步。停止使用异步无效 - 将其更改为异步任务,并确保您等待结果正常。这同样适用于你的 MainAsync 方法。 工作无效的异步方法。

有只有一个情况下,你应该看到过异步无效,这是一个传统框架的事件处理程序(例如,在的WinForms)同步范围内。如果有可能为异步方法返回一个工作,这真的,真的应该。不要打破链。

I am learning how to use async functions in console application but can't make the Task.WhenAll wait until all tasks are completed. What is wrong with the following code? It works synchronously. Thank you in advance.

static void Main(string[] args)
{
    ...
    IncluiValores(...);
    ...
}

static async void IncluiValores(...)
{
    Task<List<int>> res1 = att.GetAIDBAPI(att);
    Task<List<int>> res2 = att.GetAIDBAPI(att2);

    List<int>[] res = await Task.WhenAll(res1, res2);

    ...
}

UPDATE - Function Definition:

    public async Task<List<int>> GetAIDBAPI(Attributes attributes)
    {

        List<int> results = null;

        Connections client0 = new Connections();
        HttpClient client = client0.OpenAPIConnection(attributes.User[0], attributes.Pwd, attributes.Server, attributes.Chave, attributes.Server2);
        HttpResponseMessage response = await client.PostAsJsonAsync("api/Attributes/ID/Bulk", attributes);

        if (response.IsSuccessStatusCode)
        {
            var content = await response.Content.ReadAsStringAsync();
            results = JsonConvert.DeserializeObject<dynamic>(content).ToObject<List<int>>();
        }
        else
        {
            var content = "[{-1}]";
            var result = JsonConvert.DeserializeObject<dynamic>(content);
            results = result.ToObject<List<int>>();
        }

        return results;

    }

UPDATE 2 - Separate Context

static void Main(string[] args)
{
    AsyncContext.Run(() => MainAsync(args));
}

static async void MainAsync(string[] args)
{
    await IncluiValores(...);
}

static async Task IncluiValores(...)
{
    Task<List<int>> res1 = att.GetAIDBAPI(att);
    Task<List<int>> res2 = att.GetAIDBAPI(att2);

    List<int>[] res = await Task.WhenAll(res1, res2); // <- Error here
    //Collection was modified; enumeration operation may not execute
    ...
}
//Tried to change to code below but it does not wait.
static async Task IncluiValores(...)
{
    Task<List<int>> res1 = att.GetAIDBAPI(att);
    Task<List<int>> res2 = att.GetAIDBAPI(att2);

    await Task.WhenAll(res1, res2); // <- No error, just doesn't wait.
    list.Add(res1.Result[0]);
}
解决方案

You're calling an async void method, which inherently means you have no way of awaiting the result. Whenever you omit await, you're breaking the synchronization chain. The operation happens truly asynchronously, rather than "resynchronizing" through the await. The control is returned to the caller, while (sometime in the future) the operation resumes asynchronously.

Remember, await is a return. It's only the consistent use of await that gives you the synchronization. Stop using async void - change it to async Task and make sure you await the result properly. The same goes for your MainAsync method. Task is the void of async methods.

There's only one case where you should ever see async void, and that's within a synchronization context of a legacy framework's event handlers (e.g. in Winforms). If it's possible for an async method to return a Task, it really, really should. Don't break the chain.

这篇关于Task.WhenAll没有等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 08:26