我有一个在单击按钮后运行的 winform 代码:
void button1_Click(object sender, EventArgs e)
{
AAA();
}
async Task BBB( int delay)
{
await Task.Delay(TimeSpan.FromSeconds(delay));
MessageBox.Show("hello");
}
async Task AAA()
{
var task1 = BBB(1); // <--- notice delay=1;
var task2 = BBB(1); // <--- notice delay=1;
var task3 = BBB(1); // <--- notice delay=1;
await Task.WhenAll(task1, task2, task3);
}
问题:
为什么当 delay=1 时我一次看到一个 MessageBox:
但是如果我将延迟更改为:1,2,3 —
var task1 = BBB(1);
var task2 = BBB(2);
var task3 = BBB(3);
我看到了 - 3 个消息框,甚至没有点击任何消息框?
最佳答案
请注意,嵌套的消息循环是邪恶的,因为意外的重入实在是太难了(tm)。
我认为有两个关键的理解来解释这种行为。首先是异步延续 - 与所有其他“运行此任意代码”Win32 消息一样 - 具有比其他消息更高的优先级。第二个原因是 Win32 有一个长期存在的传统,即在运行嵌套消息循环时发送消息并同步阻塞响应。。 (附带一提,我个人认为 Win32 API 这种可怕的无处不在的重入设计是造成 Windows 上绝大多数应用程序错误的原因。
如果您以保留堆栈跟踪的方式运行代码,您可以更清楚地看到发生了什么:
void button1_Click(object sender, EventArgs e)
{
AAA();
}
private List<string> stacks = new List<string>();
async Task BBB(int delay)
{
await Task.Delay(TimeSpan.FromSeconds(delay));
var stack = new StackTrace().ToString();
stacks.Add(stack);
MessageBox.Show(stack);
}
async Task AAA()
{
var task1 = BBB(1); // <--- notice delay=1;
var task2 = BBB(1); // <--- notice delay=1;
var task3 = BBB(1); // <--- notice delay=1;
await Task.WhenAll(task1, task2, task3);
Clipboard.SetText(string.Join("\r\n\r\n", stacks));
}
Compare the dialog texts (首先是最大堆栈,然后是中等堆栈,然后是最小堆栈)在对话框全部关闭后使用剪贴板(首先是最小堆栈,然后是中等堆栈,然后是最大堆栈)。很明显,对话框是以相反的顺序显示的。
我相信这样的事情正在发生,但没有信心肯定:
MessageBox.Show。MessageBox 函数启动一个嵌套的消息循环并开始设置实际的对话框,其中包含给它自己 的消息(即设置标题、文本等)。请注意,这些调用会发送消息,但它们尚未准备好显示对话框。MessageBox.Show。当您将时间更改为 1、2、3 时,剪贴板中的堆栈仍然相同,但您会看到对话框文本现在按顺序排列(最小的堆栈在前) ,然后是中型,然后是最大)。这是因为每个 MessageBox.Show 都有足够的时间来设置消息框并建立其消息循环,并在其上的下一层之前显示对话框。
理论上,可以通过完全避免嵌套循环的 MessageBox.ShowAsync API 来避免这种奇怪的行为。不过,我不会屏住呼吸。
关于c# - async-await 的延续爆发——表现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32573672/
如何在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#窗体应用程序三.
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.
RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)
A/ctohttp://wiki.nginx.org/CoreModule#usermaster进程曾经以root用户运行,是否可以以不同的用户运行nginxmaster进程? 最佳答案 只需以非root身份运行init脚本(即/etc/init.d/nginxstart),就可以用不同的用户运行nginxmaster进程。如果这真的是你想要做的,你将需要确保日志和pid目录(通常是/var/log/nginx&/var/run/nginx.pid)对该用户是可写的,并且您所有的listen调用都是针对大于1024的端口(因为绑定(
有没有办法在sinatra的beforedoblock中停止执行并返回不同的值?beforedo#codeishere#Iwouldliketo'return"Message"'#Iwouldlike"/home"tonotgetcalled.end//restofthecodeget'/home'doend 最佳答案 beforedohalt401,{'Content-Type'=>'text/plain'},'Message!'end如果你愿意,你可以只指定状态,这里有状态、标题和正文的例子
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
我从ui中得到日期范围为-approved_between"=>"2013-03-17-2013-03-18"我需要拆分此approved_start_date="2013-03-17"和approved_end_date="2013-03-18"...我希望使用它在mysql中查询,因为mysql中的日期格式是created_at:2012-07-2810:35:01.我正在做的是:approved=approved_between.split("")approved_start_date=approved[0]approved_end_date=approved[2]很确定这不是处
response是一个散列,可能看起来像以下两种情况之一:response={'demo'=>'nil','test_01'=>'DemoData'}或response={'test'=>'DemoData','demo'=>'nil'}我想做这样的事情:ifresponse.has_key?'test_01'new_response.update(:nps_score=>response['test_01']elsenew_response.update(:nps_score=>response['test']end是否有更“Ruby”的方法来解决这个问题?也许使用||的东西运算符(