通过单击一个按钮,我需要异步调用函数f1()来启动一个长操作。当f1()运行时,我想用另一个按钮启动另一个函数f2()。当函数f1()完成时,我想认识到这一点。
我将整个过程分解为一个非常简单的示例,其中一个按钮启动一个长函数writeStars(),它每隔200毫秒就将“*”写到字符串上,总计20次。使用另一个按钮,我可以异步地将'-‘写入同一个字符串。
private async void btnStartThread1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(writeStars);
thread1.Start();
}
private void btnWriteMinus_Click(object sender, EventArgs e)
{
_Str += "-";
}
async void writeStars()
{
int count = 20;
do
{
_Str += "*";
Thread.Sleep(200);
} while (count-- > 0);
}上面的代码给出了这样的结果:‘*-*。
或者更快地单击第二个按钮:‘**--*-*。
这是真正的异步:-)
我希望使用异步任务,以便能够等待writeStars()的末尾,然后maybee按钮。我试过了,但我没有办法用任务、异步和等待来编写这个简单的示例。
发布于 2020-01-29 20:26:22
我有点不清楚您想要什么--您一开始说要在f2运行时启动f1,但接着您要求等待f1的结束,并启用f2按钮。我将回答第二种情况,在f1完成之前,您不希望运行f1。
您可以使用这样的设计(借口、语法或格式怪异,我已经很长时间没有在C#工作了):
async void btnWriteStars_Click() {
try {
btnWriteMinus.Enabled = false;
await writeStars();
} finally {
btnWriteMinus.Enabled = true;
}
}
Task WriteStars() {
return Task.Run(() => {
// much stringy goodness here
});
}策略是“写我星”事件处理程序禁用不想中断异步处理的按钮,然后等待异步处理完成,然后再次启用该按钮。
注意,仅仅完成WriteStars异步是不够的--它仍然会在调用线程上运行,直到第一个await,当然您的WriteStars没有await。因此,我们使用Task.Run或类似的函数生成异步任务,其中运行同步代码块。根据您的实际方法所做的,您可能可以将其编写为async,而不是显式地干预任务工厂--在任何情况下,关键是WriteStars返回一个任务对象以供按钮事件处理程序等待。
如果您的需求更复杂--就像您想让button2启用,但在编写星号完成之后,将其“追加减号”操作排队--那么您的设计也需要更加复杂。您可能可以将Task实例保存在表单级别,并让button2在其上执行ContinueWith,但是对于真正复杂的场景,您可能需要实现生产者-使用者方法,其中UI按钮将操作放在队列上,而工作线程则将它们取下来。但是对于简单的“Y正在运行时不要做X”的场景,禁用-等待-启用应该足够了。
https://stackoverflow.com/questions/59974766
复制相似问题