繁体   English   中英

C#如何确保一个异步方法在另一个异步方法之后执行

[英]C# How to make sure one async method executes after another async method

我已经看过一些关于asyncawait帖子以及它们如何实际工作,但我仍然有点困惑。 假设我有两个async方法,我想确保第二个方法在第一个完成后开始。 例如,考虑这样的事情:

    public async Task MyMethod(Item x)
    {
        await AddRequest(x); // 1. Add an item asynchronously 

        // make sure 2 starts after 1 completes

        await GetAllRequest(); // 2. get all items asynchronously 
    }

那么,确定这种情况的正确方法是什么?

更新:

为了尝试提供最小,完整和可验证的示例:

我在WPF应用程序中有2个WCF服务与Oracle WebCenter ContentUCM )进行通信。 这是我的代码的最小版本:

UCM服务添加新客户:

    public static async Task<ServiceResult> CheckInCustomer(Customer c)
    {
        CheckInSoapClient client = new CheckInSoapClient();
        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
        {
                // an async method in Oracle WebContent services to insert new content
                result = await client.CheckInUniversalAsync(c);
        }
        return new ServiceResult();
    }

UCM服务让所有客户:

    public static async Task<Tuple<ServiceResult, QuickSearchResponse>> GetAllCustomers()
    {
        ServiceResult error;
        var result = new QuickSearchResponse();
        SearchSoapClient client = new SearchSoapClient();
        using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
        {
                // an async method in Oracle WebContent services to search for contents
                result = await client.QuickSearchAsync(queryString);
        }
            return new Tuple<ServiceResult, QuickSearchResponse>(error, result);
    }

添加Customer Async方法,该方法绑定到UI中的Button命令:

    private async Task AddCustomer()
    {
        var result = await CheckInCustomer(NewCustomer);
        if (!result.HasError)
            await GetAllCustomers();
    }

    public ICommand AddCustomerCommand
    {
        get
        {
            _addCustomerCommand = new RelayCommand(async param => await AddCustomer(), null);
        }
    }

获取所有Customer Async方法( Items绑定到UI中的DataGrid ):

    private async Task GetAllCustomers()
    {
        Items.Clear();
        var searchResult = await GetCustomersInfoAsync();
        if (!searchResult.HasError)
        {
            foreach (var item in searchResult)
                Items.Add(new CustomerVm(item));
        }
    }

现在,当我添加一个新Customer ,我希望在我首先插入客户然后获得所有客户时,在DataGrid看到新创建的项目。 但是这个代码以随机方式运行,这意味着有时列表会在插入后几秒钟显示新创建的客户,有时则不会。

您提供的代码实际上可以满足您的需求。

public async Task MyMethod(Item x)
{
    await AddRequestAsync(x); 

    await GetAllRequestAsync(); 
}

但是,如果你在谈论它们之间不可预测的“非常短暂”的延迟,并且你想确保没有延迟,那就不可能了。

等待 - (优先,必须在ContinueWith上使用)(TY到@Taffer和@Michael注释)等待新创建的任务完成并确保等待任务的执行完成后继续。

在转移到GetAllRequest之前,您的第一个函数AddRequest将提供结果。

public async Task MyMethod(Item x)
    {
        await AddRequest(x);

        await GetAllRequest();
    }

我在这里不明白的是,异步意味着第一种方法可以保持未完成状态,并且主要任务的执行仍在继续。 因此,第二种方法的某些部分可能在第一种方法完成之前运行。

它被称为异步编程,因为当遇到await关键字(类似于迭代器中的yield)时,程序的运行时捕获状态会在等待任务完成后恢复状态,因此继续在正确的上下文中运行。

但是如果你想在第一个任务之后运行它,那么你就可以做到。

使用ContinueWith - 该任务可用的方法允许在任务完成执行后执行代码。 简单来说,它允许继续。

 public async Task MyMethod(Item x)
    {
        var req = AddRequest(x).ContinueWith(async (t1) =>
               {
                  await GetAllRequest();
               }); 
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM