我最近一直在处理 async await(阅读所有可能的文章,包括 Stephen 和 Jon 的最后两章),但我已经得出结论,但我不知道它是否是100% 正确。 - 因此我的问题。
因为 async 只允许出现 await 这个词,所以我将把 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 ...
}
当线程到达 await workTask; 时,它将方法拆分为 2 个部分。所以在 SimulateWork 完成后 - 方法的延续:又名://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
}
这里 - 我不需要需要 continuation ,意思是 - 我不需要 await 来拆分方法,这意味着 - 我不需要 async/await 完全在这里!但我仍然会得到相同的结果/行为!
所以我可以这样做:
public void ProcessAsync()
{
SimulateWork();
}
问题:
最佳答案
所以,你认为 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
}
首先,我假设 “当 await 是最后一个” 你的意思是 “当 await 是唯一的 await "。必须是这样,否则以下内容将无法编译:
public async Task ProcessAsync()
{
await Task.Delay(1000);
Task<string> workTask = SimulateWork();
return workTask;
}
现在,如果它是唯一的 await ,你确实可以这样优化它:
public Task ProcessAsync()
{
Task<string> workTask = SimulateWork();
return workTask;
}
但是,它会给您带来完全不同的异常传播行为,这可能会产生一些意想不到的副作用。问题是,现在可能会在调用者的堆栈上抛出异常,这取决于 SimulateWork 的方式。是内部实现的。我发布了 detailed explanation of this behavior . async 通常不会发生这种情况Task/Task<>方法,其中异常存储在返回的 Task 中目的。对于 async void 仍然可能发生方法,但这是一个 different story .
因此,如果您的调用者代码已准备好应对异常传播中的此类差异,那么跳过 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);
}
你可以这样调用它:
public Task ProcessAsync()
{
QueueTaskAsync(SimulateWork());
}
目标是立即在当前线程的同步上下文中抛出致命异常(例如,内存不足),而任务结果/错误处理被推迟到适当的时候。
关于使用即发即弃任务的有趣讨论here .
关于c# - 等待最后一次时不必要的异步/等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23382851/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里
我是HanamiWorld的新人。我已经写了这段代码:moduleWeb::Views::HomeclassIndexincludeWeb::ViewincludeHanami::Helpers::HtmlHelperdeftitlehtml.headerdoh1'Testsearchengine',id:'title'hrdiv(id:'test')dolink_to('Home',"/",class:'mnu_orizontal')link_to('About',"/",class:'mnu_orizontal')endendendendend我在模板上调用了title方法。htm
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
-if!request.path_info.include?'A'%{:id=>'A'}"Text"-else"Text"“文本”写了两次。我怎样才能只写一次并同时检查path_info是否包含“A”? 最佳答案 有两种方法可以做到这一点。使用部分,或使用content_forblock:如果“文本”较长,或者是一个重要的子树,您可以将其提取到一个部分。这会使您的代码变干一点。在给出的示例中,这似乎有点矫枉过正。在这种情况下更好的方法是使用content_forblock,如下所示:-if!request.path_info.inc