Roy*_*mir 15 .net c# task-parallel-library async-await c#-5.0
我最近一直在处理异步等待(阅读包括Stephen和Jon最后两章在内的所有可能的文章),但我得出结论,我不知道它是否100%正确. - 因此我的问题.
由于 async只允许单词等待出现,我将async不谈.
AFAIU等待着继续.而不是编写功能(连续)代码,编写同步代码.(我想把它称为可回调代码)
因此,当编译器到达时await- 它将代码分成2个部分,并在第一部分完成后注册要执行的第二部分(我不知道为什么callback不使用该字- 这正是所做的).(同时工作 - 线程回来做其他事情).
但看看这段代码:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
string st= await workTask;
//do something with st
}
public Task <string> SimulateWork()
{
return ...
}
Run Code Online (Sandbox Code Playgroud)
当线程到达时await workTask;,将方法拆分为2个部分.所以在SimulateWork完成之后 - 方法的继续:AKA://do something with st- 被执行.
一切都好
但是,如果方法是:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
await workTask; //i don't care about the result , and I don't have any further commands
}
Run Code Online (Sandbox Code Playgroud)
在这里-我并不需要延续,意思是-我不需要await分割方法,这意味着-我不需要异步/等候在这里了! 而且我仍然会有相同的结果/行为!
所以我可以这样做:
public void ProcessAsync()
{
SimulateWork();
}
Run Code Online (Sandbox Code Playgroud)
题:
nos*_*tio 14
因此,您认为await以下内容是多余的,因为问题标题暗示:
public async Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
await workTask; //i don't care about the result , and I don't have any further
}
Run Code Online (Sandbox Code Playgroud)
首先,我假设在"何时await是最后"你的意思是"当它await是唯一的await "时.它必须是这样,因为否则以下就不会编译:
public async Task ProcessAsync()
{
await Task.Delay(1000);
Task<string> workTask = SimulateWork();
return workTask;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果它是唯一的 await,你可以像这样优化它:
public Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
return workTask;
}
Run Code Online (Sandbox Code Playgroud)
但是,它会为您提供完全不同的异常传播行为,这可能会产生一些意想不到的副作用.问题是,现在可能会在调用者的堆栈上抛出异常,具体取决于SimulateWork内部实现的方式.我发布了这种行为的详细解释.这通常不会发生在async Task/ Task<>methods中,其中异常存储在返回的Task对象中.它仍然可能发生在一种async void方法中,但这是一个不同的故事.
因此,如果您的调用者代码已准备好应对异常传播中的这些差异,那么最好跳过async/await任何可能的地方并简单地返回Task.
另一个问题是,如果你想发出一个即发即弃的电话.通常,您仍希望以某种方式跟踪已触发任务的状态,至少是出于处理任务异常的原因.我无法想象一个案例,我真的不在乎任务是否永远不会完成,即使它所做的只是记录.
因此,对于即发即忘而言,我通常使用辅助async void方法将待处理任务存储在某处以供以后观察,例如:
readonly object _syncLock = new Object();
readonly HashSet<Task> _pendingTasks = new HashSet<Task>();
async void QueueTaskAsync(Task task)
{
// keep failed/cancelled tasks in the list
// they will be observed outside
lock (_syncLock)
_pendingTasks.Add(task);
try
{
await task;
}
catch
{
// is it not task's exception?
if (!task.IsCanceled && !task.IsFaulted)
throw; // re-throw
// swallow, but do not remove the faulted/cancelled task from _pendingTasks
// the error will be observed later, when we process _pendingTasks,
// e.g.: await Task.WhenAll(_pendingTasks.ToArray())
return;
}
// remove the successfully completed task from the list
lock (_syncLock)
_pendingTasks.Remove(task);
}
Run Code Online (Sandbox Code Playgroud)
你这样称呼它:
public Task ProcessAsync()
{
QueueTaskAsync(SimulateWork());
}
Run Code Online (Sandbox Code Playgroud)
目标是在当前线程的同步上下文中立即抛出致命异常(例如,内存不足),同时延迟任务结果/错误处理直到适当.
还有的是利用工作的一个有趣的讨论,发射后不管这里.
i3a*_*non 10
你很亲密 这意味着你可以像这样写:
public Task ProcessAsync()
{
// some sync code
return SimulateWork();
}
Run Code Online (Sandbox Code Playgroud)
这样你就不会"支付"标记方法的开销,async但你仍然有能力等待整个操作.
PS:这是一项关于常见误用的研究async-await:
| 归档时间: |
|
| 查看次数: |
4369 次 |
| 最近记录: |