使用C#将同步方法转换为异步

时间:2015-03-03 10:03:21

标签: c# asynchronous async-await task

我有两种方法。我想等待第一个,有时等待另一个(但不是所有的时间)。所以我想我应该使用一个任务,当我想等待时等待它,当我不想等待时,不要等待它。

编辑:事实上,我只需要一场火灾而忘记打电话? :

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 个答案:

答案 0 :(得分:2)

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

在.Net 4.5.2之前处理AspNet上的后台任务,你不应该“触发并忘记”异步方法,因为线程可以在任务结束之前中止。从4.5.2开始,您可以使用HostingEnvironment.QueueBackgroundWorkItem

答案 1 :(得分: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;
        }

这样就等待Task:控制权返回给调用者,然后调用者可以决定是等待还是等待,或者在阻塞当前线程时等待Task。 / p>

您可能希望将操作更改为async并将呼叫更新为:

string jobId = await runner.Run();

或者您可以使用Task<string>

执行相同操作
var task = runner.Run();
task.Wait();
string jobId = task.Result;

编辑:重要的是LongMethodICouldWantToWaitOrNot是否正在进行CPU绑定操作,在这种情况下,使用Task.Run运行它是否有意义,或者是否“慢”&#39;该方法是由I / O操作引起的,在这种情况下你应该使它async,我看不出任何同步运行它的原因