C # Как ждать асинхронную задачу, пока она не указывает на продолжение - PullRequest
0 голосов
/ 25 августа 2018

У меня есть метод C #, который несколько раз вызывает внешний веб-сервис в цикле. Мне нужно вызвать его асинхронно в другом потоке.

Но вызывающий процесс ДОЛЖЕН ждать, пока асинхронный поток не выполнит определенное условие, - это условие возникает задолго до завершения итераций цикла.

Пожалуйста, предложите пример кода на C #, который описывает, как ждать, пока асинхронный блок кода покажет, что определенное условие выполнено, чтобы основной процесс мог продолжаться, не дожидаясь завершения цикла.

Мой код:

..
List<MyObject> objList = GetObjects();
int counter = 0;
await Task.Factory.StartNew(() =>
{
    foreach (MyObject obj in objList)
    {
        counter++;
        CallExtWebSvc(obj);
        if (counter == 1)
        {
            // return an indication that main process can proceed.
        }
    }
});

// Do other stuff...

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

Если вы хотите избежать опасности «выстрелить и забыть» или вам также нужно дождаться завершения полной операции, вы можете вернуть две задачи (Task,Task) (синтаксис C # v7). Вызывающая сторона будет ждать обе задачи по порядку.

public async Task Caller()
{
    var (partOne,partTwo) = DoSomethingAsync();

    await partOne;
    //part one is done...

    await partTwo;
    //part two is done...
}

public (Task,Task) DoSomethingAsync()
{
    var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
    return (tcs.Task, DoWork(tcs));
}

public async Task DoWork(TaskCompletionSource<bool> tcs)
{
    List<MyObject> objList = GetObjects();
    int counter = 0;
    await Task.Run(() =>
    {
        foreach (MyObject obj in objList)
        {
            counter++;
            CallExtWebSvc(obj);
            if (counter == 1)
            {
                // return an indication that main process can proceed.
                tcs.SetResult(true);
            }
        }
    });

    // Do other stuff...
}
0 голосов
/ 25 августа 2018

Вы можете выполнить свой метод как fire и забыть, а затем ждать TaskCompletionSource. Этот TaskCompletionSource передается методу, который вызывает веб-сервис в качестве параметра. Затем метод устанавливает результат в TaskCompletionSource в какой-то момент.

Вот пример кода:

        public async Task DoWebserviceStuffAsync(TaskCompletionSource<bool> taskCompletionSource)
        {
            for (int i = 0; i < 10; i++)
            {
                //your webservice call
                await Task.Delay(5000);

                //some condition
                if (i == 1)
                {
                    //after setting this your CallingMethod finishes 
                    //waiting the await taskCompletionSource.Task;
                    taskCompletionSource.TrySetResult(true);
                }
            }
        }

        private async Task CallerMethod()
        {
            var taskCompletionSource = new TaskCompletionSource<bool>();

            //call method without await
            //care: You cannot catch exceptions without await
            DoWebserviceStuffAsync(taskCompletionSource);

            //wait for the DoWebserviceStuffAsync to set a result on the passed TaskCompletionSource
            await taskCompletionSource.Task;
        }
...