简体   繁体   English

C#如何等待异步任务,直到它指示继续

[英]C# How to await async task until it indicates to proceed

I have a C# method, which calls an external web service multiple times, in a loop. 我有一个C#方法,可以循环调用多次外部Web服务。 I need to call it asynchronously in a different thread. 我需要在另一个线程中异步调用它。

But the caller process MUST wait until the async thread meets a certain condition, - this condition occurs much before the loop iterations complete. 但是调用者进程必须等到异步线程满足某个条件为止-这种条件发生在循环迭代完成之前。

Please suggest a C# code example which describes how to wait until the async block of code indicates that a certain condition has been met, so that the main process can proceed without waiting for loop to finish. 请提出一个C#代码示例,该示例描述如何等待直到异步代码块指示已满足特定条件,以便主进程可以继续执行而无需等待循环完成。

My code: 我的代码:

..
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...

You could execute your method as fire and forget and then wait for a TaskCompletionSource. 您可能会像火灾一样执行方法而忘记了,然后等待TaskCompletionSource。 This TaskCompletionSource is given to the method that calls the webservice as parameter. 该TaskCompletionSource被提供给调用webservice作为参数的方法。 The method then sets a result on the TaskCompletionSource at some point. 然后,该方法会在某个时刻在TaskCompletionSource上设置结果。

Here is an example code piece: 这是一个示例代码段:

        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;
        }

If you want to avoid the danger of "fire and forget" or you also need to wait for the full operation to complete, you could return two tasks (Task,Task) (C# v7 syntax). 如果要避免发生“失火”的危险,或者还需要等待完整的操作完成,则可以返回两个任务(Task,Task) (C#v7语法)。 The caller would await both tasks in order. 呼叫者将依次等待两个任务。

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...
}

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

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