使用 C# 将同步方法转换为异步
Transform a sync method to async with C#
我有两个方法。我想等第一个,有时要等另一个(但不是所有时间)。所以我觉得应该用task,想等的时候await,不想等的时候不await。
编辑:事实上,我只需要一个 fire and forget 调用? :
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)
{
// ...
}
}
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);
}
}
在 AspNet 上处理后台任务,在 .Net 4.5.2 之前,您不应该 "fire and forget" 异步方法,因为线程可以在任务结束前中止。从 4.5.2 开始,您可以使用 HostingEnvironment.QueueBackgroundWorkItem
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
.
您可能希望将操作更改为 async
并将调用更新为:
string jobId = await runner.Run();
或者您可以使用 Task<string>
来做同样的事情
var task = runner.Run();
task.Wait();
string jobId = task.Result;
编辑:重要的是 LongMethodICouldWantToWaitOrNot 是否正在执行 CPU 绑定操作,在这种情况下使用 Task.Run
运行 它是有意义的,或者 [=27=该方法的 ] 是由 I/O 操作引起的,在这种情况下,您应该将其设置为 async
并且我看不出有任何理由 运行 同步它
我有两个方法。我想等第一个,有时要等另一个(但不是所有时间)。所以我觉得应该用task,想等的时候await,不想等的时候不await。
编辑:事实上,我只需要一个 fire and forget 调用? :
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)
{
// ...
}
}
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);
}
}
在 AspNet 上处理后台任务,在 .Net 4.5.2 之前,您不应该 "fire and forget" 异步方法,因为线程可以在任务结束前中止。从 4.5.2 开始,您可以使用 HostingEnvironment.QueueBackgroundWorkItem
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
.
您可能希望将操作更改为 async
并将调用更新为:
string jobId = await runner.Run();
或者您可以使用 Task<string>
var task = runner.Run();
task.Wait();
string jobId = task.Result;
编辑:重要的是 LongMethodICouldWantToWaitOrNot 是否正在执行 CPU 绑定操作,在这种情况下使用 Task.Run
运行 它是有意义的,或者 [=27=该方法的 ] 是由 I/O 操作引起的,在这种情况下,您应该将其设置为 async
并且我看不出有任何理由 运行 同步它