我是C#异步等待机制的新手。我已经检查了异步的所有先前示例,等待,但是没有一个与我的完全一样。我想做什么?我有一个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
}
答案 0 :(得分:5)
await
暂停方法的执行,直到参数(实际上必须为Task
或Task
之类的参数(必须为Task<T>
)为止。您的问题实际上是我遇到过多次的问题:
如何异步等待某些事件被触发
在您的情况下,“某些事件”是单击按钮。幸运的是,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>
)。仅当在TCS对象上调用TrySetResult
时,该任务才能完成。在按钮单击处理程序(或WPF的命令处理程序)中执行以下操作:
clickWaitTask.TrySetResult(true); //Value does not matter
正如评论者所指出的那样,除非您处于事件处理程序中,否则不应该使用async void
,并且在这种情况下,应在方法周围使用try/catch
以避免未处理的异常带来麻烦。我也非常警惕您的public static
,但这是一个单独的问题。