Immediately assignment for a call built inside a ContinueWith block?

First, an apology for the title; I couldn't think of a way to summarize what I am trying to do.

I have the following two functions:

Main code:

private async Task<PreparationInfo> PrepareRoundtrip()
{
    PreparationInfo output = new PreparationInfo();

    Task.Delay(3000); // stands in for a call to the server to fetch data for how to prepare

    prepare(output) // package result into output

    return output;
}

private Task ExecuteWithPrepare()
{
    if (!PrepareEnabled) // instance variable
        return stateObject.Execute();
    else
    {
        Task<PreparationInfo> prepareTask = PrepareRoundtrip();
        return tceTask.ContinueWith((prepareTaskInternal) =>
        {
            stateObject.Execute(); // this is the Task that I need to return
        });
    }
}

      

stateObject.Execute () header:

internal Task Execute()
{
    ...
}

      

I am writing a wrapper for a method stateObject.Execute()

that will pre-request a prepare ( PrepareRoundtrip()

) method to handle some parameters before executing.

If preparation is not activated ( PrepareEnabled == false

), I can just call the direction Execute()

and immediately return the returned task. If provisioning is enabled, I need to run the provisioning method (which is unique to this task, I can modify it as needed), then run Execute()

.

The part I'm stuck on is:

The entire function should run and return as if it were stateObject.Execute()

called directly, with only the part added PrepareRoundtrip()

, which meant two things:

  • The task returned from ExecuteWithPrepare()

    must represent the task being returned stateObject.Execute()

    .

  • ExecuteWithPrepare()

    should return immediately (i.e. not wait for the 3 second delay in PrepareRoundtrip()

What's the best way to achieve this? Thank!

TL; DR:

Adding a wrapper stateObject.Execute()

to add an extra preparation step that is potentially long; everything is needed to immediately return a task that represents the original result, and not wait for the completion of the first stage of preparation.

+3


source to share


2 answers


You shouldn't use ContinueWith

at all. This is a deprecated method with dangerous behavior (in particular, it will use the current task scheduler).

Instead, just use await

:



private Task ExecuteWithPrepareAsync()
{
  if (!PrepareEnabled)
    return stateObject.ExecuteAsync();
  else
    return PrepareAndExecuteAsync();
}

private async Task PrepareAndExecuteAsync()
{
  await PrepareRoundtripAsync();
  await stateObject.ExecuteAsync();
}

      

Also notice the naming convention Async

, part of the TAP pattern .

0


source


  • Use Unwrap

    to turn Task<Task>

    (this is what you have) into Task

    representing the completion of the internal Task

    , without waiting for the external task to complete synchronously.

  • Just await

    Task<Task>

    twice, not once if in a method async

    .



+1


source







All Articles