我是 c# 异步等待机制的新手。我已经检查了所有之前的 async, await 示例,但没有一个与我的完全相同。我想做什么?我有一个 foreach 循环,我想按特定规则停止它,做一些事情并通过单击按钮继续运行。
这是一个简单的代码示例:
private void RunConvert() // START
{
foreach (PartSettings File in PartsFromXLS) // RUNING THE FOREACH LOOP ON A LIST
{
ProcessSinglePart(PathStep, PathMCX);
}
}
public static async void ProcessSinglePart(string PartPathToRead, string PartPathToSave)
{
// DO SOME STUFF BEFORE THE CHECK
if (PartLength < PartWidth) // SOME CHECK VALUES
{
await WhenClicked(); //HERE I WOULD LIKE TO WAIT FOR BUTTON CLICK
}
//DO SOME STUFF AFTER THE CHECK
}
private void GeometryOK_Click(object sender, EventArgs e)
{
// I WOULD LIKE TO WAIT FOR THIS CLICK
}
await
暂停方法的执行,直到参数(必须是 Task
,实际上,它只是一个 Task
或 Task<T>
)完成。您的问题实际上是我遇到过很多次的问题:
How to asynchronously wait for some event to be fired
在您的情况下,“某些事件”是单击按钮。幸运的是,TaskCompletionSource<T>
(以下简称 TCS)非常适合解决这个问题。首先在类级别声明一个 TCS:
private TaskCompletionSource<bool> clickWaitTask;
没有非通用版本的 TCS,所以我通常只使用 bool
.在这种情况下,我们实际上并不关心数据。然后你的方法看起来像这样(后面的解释):
public static async void ProcessSinglePart(string PartPathToRead, string PartPathToSave)
{
// DO SOME STUFF BEFORE THE CHECK
clickWaitTask = new TaskCompletionSource<bool>();
if (PartLength < PartWidth) // SOME CHECK VALUES
{
await clickWaitTask.Task;
}
//DO SOME STUFF AFTER THE CHECK
}
您创建一个新的 TCS,以便每次运行此逻辑时,它都会等待点击发生。然后你等待 Task
属性(实际上是 Task<T>
)。该任务只会在 TrySetResult
时完成在 TCS 对象上调用。在您的按钮单击处理程序(或 WPF 的命令处理程序)中执行此操作:
clickWaitTask.TrySetResult(true); //Value does not matter
正如一位评论者所说,您不应该使用 async void
除非你在事件处理程序中,并且应该有 try/catch
在这种情况下围绕该方法避免一些未处理的异常的麻烦。我也非常警惕你的public static
但这是一个单独的问题。