簡體   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