Force loop to wait for an event

前端 未结 3 1617
梦毁少年i
梦毁少年i 2020-12-12 05:07

I am trying to write a method that goes through a list of items - for each one adds it to a form, then waits for the user to input some data and click a button. However I ha

3条回答
  •  旧时难觅i
    2020-12-12 05:47

    While I agree in general with Jon Skeet, there was an interesting presentation by Mads Torgensen demonstrating how async/await can be used to simplify such scenarios (using the techniques mentioned by Jon). After all, isn't that the same as with enumerators - we can write own enumerator class using state like index etc., but we almost never do that and use iterator blocks instead.

    Anyway, here is the async/await technique we were talking about.

    First, the reusable part:

    public static class Utils
    {
        public static Task WhenClicked(this Button button)
        {
            var tcs = new TaskCompletionSource();
            EventHandler onClick = null;
            onClick = (sender, e) =>
            {
                button.Click -= onClick;
                tcs.TrySetResult(null);
            };
            button.Click += onClick;
            return tcs.Task;
        }
    }
    
    
    

    and your code using it (note that you need to mark your method as async)

    foreach (string s in List)
    {
        txtName.Text = s;
        await yourButton.WhenClicked();
    }
    

    Sample test putting it all together:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Samples
    {
        static class Test
        {
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                var form = new Form();
                var txtName = new TextBox { Parent = form, Top = 8, Left = 8 };
                var buttonNext = new Button { Parent = form, Top = txtName.Bottom + 8, Left = 8, Text = "Next" };
                form.Load += async (sender, e) =>
                {
                    var List = new List { "A", "B", "C", "D " };
                    foreach (string s in List)
                    {
                        txtName.Text = s;
                        await buttonNext.WhenClicked();
                    }
                    txtName.Text = "";
                    buttonNext.Enabled = false;
                };
                Application.Run(form);
            }
        }
        public static class Utils
        {
            public static Task WhenClicked(this Button button)
            {
                var tcs = new TaskCompletionSource();
                EventHandler onClick = null;
                onClick = (sender, e) =>
                {
                    button.Click -= onClick;
                    tcs.TrySetResult(null);
                };
                button.Click += onClick;
                return tcs.Task;
            }
        }
    }
    
        

    提交回复
    热议问题