С# приостановить цикл foreach, пока не будет нажата кнопка

Используя С#, у меня есть список методов (действий). Затем у меня есть метод для вызова действия с использованием цикла foreach. Нажатие кнопки вызывает метод, который, в свою очередь, вызывает все действия в списке за один раз. Мне нужно, чтобы щелчок выполнял только одно действие за щелчок. Заранее спасибо.

private static List<Action> listOfMethods= new List<Action>();

listOfMethods.Add(() => method1());
listOfMethods.Add(() => method2());
listOfMethods.Add(() => method3());
//====================================================================
private void invokeActions()
{
   foreach (Action step in listOfMethods)
   {
       step.Invoke();
       //I want a break here, only to continue the next time the button is clicked
   }
}
//====================================================================
private void buttonTest_Click(object sender, EventArgs e)
    {
        invokeActions();
    }

person justlearning    schedule 03.09.2015    source источник
comment
Почему вы решили использовать List<Action>? Сколько раз вы планируете повторять структуру? Это только один раз, пока не будут вызваны все методы, или вы планируете цикл? В зависимости от вашего намерения, Stack или Queue может быть лучшим выбором.   -  person Ian R. O'Brien    schedule 03.09.2015
comment
Честно говоря, потому что я новичок в программировании и не знал об этом :)   -  person justlearning    schedule 03.09.2015


Ответы (4)


Вы можете добавить счетчик шагов:

private static List<Action> listOfMethods= new List<Action>();
private static int stepCounter = 0;

listOfMethods.Add(() => method1());
listOfMethods.Add(() => method2());
listOfMethods.Add(() => method3());
//====================================================================
private void invokeActions()
{
       listOfMethods[stepCounter]();

       stepCounter += 1;
       if (stepCounter >= listOfMethods.Count) stepCounter = 0;
}
//====================================================================
private void buttonTest_Click(object sender, EventArgs e)
    {
        invokeActions();
    }
person Bruno    schedule 03.09.2015
comment
Спасибо и всем остальным. Я использовал это решение в конце. - person justlearning; 03.09.2015

Вам нужно сохранять какое-то состояние между нажатиями кнопок, чтобы вы знали, где вы остановились в прошлый раз. Я предлагаю использовать простой счетчик:

private int _nextActionIndex = 0;

private void buttonTest_Click(object sender, EventArgs e)
{
    listOfMethods[_nextActionIndex]();
    if (++_nextActionIndex == listOfMethods.Count)
        _nextActionIndex = 0;    // When we get to the end, loop around
}

При этом выполняется первое действие, затем следующее и т. д. при каждом нажатии кнопки.

person Cameron    schedule 03.09.2015

Сначала напишите метод для генерации Task при следующем нажатии определенного Button:

public static Task WhenClicked(this Button button)
{
    var tcs = new TaskCompletionSource<bool>();
    EventHandler handler = null;
    handler = (s, e) =>
    {
        tcs.TrySetResult(true);
        button.Click -= handler;
    };
    button.Click += handler;
    return tcs.Task;
}

Затем просто await в своем методе, когда вы хотите, чтобы он продолжался после следующего нажатия кнопки:

private async Task invokeActions()
{
    foreach (Action step in listOfMethods)
    {
        step.Invoke();
        await test.WhenClicked();
    }
}
person Servy    schedule 03.09.2015

Если вам нужно выполнить методы только один раз, я бы предложил добавить их в Queue<T>, чтобы состояние не нужно было поддерживать.

private static Queue<Action> listOfMethods = new Queue<Action>();
listOfMethods.Enqueue(method1);
listOfMethods.Enqueue(method2);
listOfMethods.Enqueue(method3);   

private void buttonTest_Click(object sender, EventArgs e) {
    if (listOfMethods.Count > 0) {
        listOfMethods.Dequeue().Invoke();
    }
}
person Ian R. O'Brien    schedule 03.09.2015