2

I have two methods. I want to wait the first one and some times wait the other (but not all the time). So I think I should use a task and await it when I want to wait, and not await it when I don't want to wait.

EDIT : in fact, I only need a fire and forget call ? :

public class TestController : ApiController
{
    public IHttpActionResult Get(int id)
    {
        Stopwatch sw = Stopwatch.StartNew();

        JobRunner runner = new JobRunner();
        bool iWantToWait = id == 1;

        string jobId = runner.Run(!iWantToWait);
        sw.Stop();
        return Ok("Ok " + jobId + " # " + sw.Elapsed );
    }
}

public class JobRunner
{
    public string Run(bool fireAndForget)
    {
        ShortMethodIAlwaysWantToWait();
        string jobId = Guid.NewGuid().ToString("N");
        if (fireAndForget)
            HostingEnvironment.QueueBackgroundWorkItem(token => LongMethodICouldWantToWaitOrNot(jobId));
        else
            LongMethodICouldWantToWaitOrNot(jobId);
        return jobId;
    }

    private void ShortMethodIAlwaysWantToWait()
    {
        // ...
    }

    private void LongMethodICouldWantToWaitOrNot(string jobId)
    {
        // ...
    }
}

2 Answers 2

3
public class JobRunner
{
    public async Task<string> Run(bool fireAndForget)
    {
        await ShortMethodIAlwaysWantToWait();
        string jobId = Guid.NewGuid().ToString("N");
        if (fireAndForget)
            HostingEnvironment.QueueBackgroundWorkItem((token) => LongMethodICouldWantToWaitOrNot(jobId));
        else
            await LongMethodICouldWantToWaitOrNot(jobId);
        return jobId;
    }

    private async Task LongMethodICouldWantToWaitOrNot(string jobId)
    {
        await Task.Delay(5000);
    }

    private async Task ShortMethodIAlwaysWantToWait()
    {
        await Task.Delay(2000);
    }
}

Take care of background Task on AspNet, before .Net 4.5.2, you shouldn't "fire and forget" an async method, since the Thread can be aborted before the end of the Task. Since 4.5.2 you can use HostingEnvironment.QueueBackgroundWorkItem

Sign up to request clarification or add additional context in comments.

15 Comments

You're not awaiting ShortMethodIAlwaysWantToWait
although note that this changes the behaviour slightly since LongMethod is now run on the same thread. Easily modifiable to run on another thread with await Task.Run() though.
Thanks for your answer. Thread.Sleep is of course an example, I'm accessing some ressources. Do I need to have an async LongMethodICouldWantToWaitOrNot ? Or can it only be a void ?
Usually, all methods taking longer than 40 or 50 ms should be transformed as a Task. If resources are on network or on disk, the answer is directly yes.
|
0
        public async Task<string> Run()
        {
            ShortMethodIAlwaysWantToWait();
            string jobId = Guid.NewGuid().ToString("N");

            if (iwantToAWait) {
                var task = Task.Run(() => LongMethodICouldWantToWaitOrNot(jobId));
                await task;
            }
            else
               LongMethodICouldWantToWaitOrNot(jobId)

            return jobId;
        }

This way the Task is either awaited: the control is returned to the caller, who then can decide whether to wait or await, or the Task is waited for while blocking the current thread.

You may want to either change your action to be async and update the call to:

string jobId = await runner.Run();

Or you can do the same using Task<string>

var task = runner.Run();
task.Wait();
string jobId = task.Result;

Edit: it is important whether the LongMethodICouldWantToWaitOrNot is doing CPU bound operation, in which case it make sense to run it with Task.Run, or whether the 'slowness' of the method is caused by I/O operations in which case you should make it async and I cannot see any reason for running it synchronously

4 Comments

Wait inside async method? and What's the point in executing in threadpool thread and waiting for it synchronously? Why not just call LongMethodICouldWantToWaitOrNot?
That's what OP asked for. I not a proponent of challenging the questions. He wants to Wait or await depending on something... executing in threadpool is indeed unnecessary.. updating the answer.
I read the question as sometimes await and sometimes not. I can't see where OP asked to wait synchronously. Really question is unclear atleast for me. But, if you want to wait synchronously inside async method, you're doing something terribly wrong.
In this very specific case the await allows to return the control to the caller. The caller can then run other things, which will be in parallel to LongMethodICouldWantToWaitOrNot. @Sriram "But, if you want to wait synchronously inside async method, you're doing something terribly wrong" would you care to explain? Opinionated statements without factual explanation are the best tool in any discourse! ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.