如何继续浏览具有多个循环并等待用户反馈的 UI

本文关键字:循环 等待 用户反馈 UI 何继续 继续 浏览 | 更新日期: 2023-09-27 18:31:49

我用C#编写并使用.net Framework 3.5。我正在运行多个循环,每次迭代时构建 UI,然后等待用户反馈(等待通过或失败按钮单击)。以下是我要做的:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        // add both button handlers to function btn_Click
        for(int test = 0; test < 5; test++)
           for(int variation = 0; variation < 4; variation++)
              for(int subtest = 0; subtest < 3; subtest++)
              {
                // call function to update GUI
                // may need to do stuff while at this state
                // wait for user to click pass/fail button
              }
    }
    private void btn_Click(object sender, EventArgs e)
    {
        // pass button pressed, inform for loop to iterate to next test
        // if fail button, then stop tests
    }
}

for 循环内的等待是让我得到的。由于这是单线程的,我遇到了 Sleep 问题,并且不喜欢将按钮按下的检查放在带有全局变量的 while 循环中的想法。我尝试自动重置事件来等待按钮单击,但这也给了我问题。处理此问题的最佳方法是什么?

我确实以一种可以尝试实现它的方式编写了代码,但我认为这不是一个非常优雅的解决方案:

public partial class Form1 : Form
{
    int test;
    int variation;
    int subtest;
    public Form1()
    {
        InitializeComponent();
        test = 0;
        variation = 0;
        subtest = 0;
        // update GUI
        btnUpdate.Text = "Hello # " + test.ToString() + "." + variation.ToString() + "." + subtest.ToString();
    }
    private void btnUpdate_Click(object sender, EventArgs e)
    {
        subtest++;
        if (test >= 5)
            if (variation >= 4)
                if (subtest >= 3)
                {
                    // done case
                    Console.WriteLine("Tests are complete");
                    btnUpdate.Visible = false;
                }
        if (subtest > 3)
        {
            subtest = 0;
            variation++;
        }
        if (variation > 4)
        {
            variation = 0;
            test++;
        }
        Console.WriteLine("I was clicked");
        // update button
        btnUpdate.Text = "Hello # " + test.ToString() + "." + variation.ToString() + "." + subtest.ToString();
    }
}

提前感谢!

如何继续浏览具有多个循环并等待用户反馈的 UI

对于这种情况,线程是矫枉过正的。你只需要做一些代码清理和重构,它会立即看起来更好和合乎逻辑。

public class LoopCounter
{
    int test = 0;
    int variation = 0;
    int subtest = 0;
    const int MAX_TEST = 5;
    const int MAX_VARIATION = 4;
    const int MAX_SUBTEST = 3;
    public int Test {get{return test;}}
    public int Variation {get{return variation;}}
    public int Subtest {get{return subtest;}}
    public bool DoNext()
    {
        if (test >= MAX_TEST) // test for end all cycling
            return false;
        subtest++;
        if (subtest < MAX_SUBTEST)
            return true;
        subtest = 0;
        variation ++;
        if (variation < MAX_VARIATION)
            return true;
        variation = 0;
        test++;
        if (test < MAX_TEST)
            return true;
        return false;
    }
}

然后,您可以轻松使用此代码,如下所示:

public partial class Form1 : Form
{
    LoopCounter counter = new LoopCounter();
    public Form1()
    {
        InitializeComponent();
        UpdateUI();
    }
    private void UpdateUI()
    {
        // update GUI
        btnUpdate.Text = "Hello # " + counter.Test.ToString() + "." + counter.Variation.ToString() + "." + counter.Subtest.ToString();
    }
    private void btnUpdate_Click(object sender, EventArgs e)
    {
        Console.WriteLine("I was clicked");
        if (counter.DoNext())
        {
            UpdateUI();
        }
        else
        {
            // done case
            Console.WriteLine("Tests are complete");
            btnUpdate.Visible = false;
        }
    }
}

只需使用单独的线程来更新UI并在未按下按钮时阻止它:

public partial class Form1 : Form
{
    AutoResetEvent are = new AutoResetEvent(true);
    public Form1()
    {
        InitializeComponent();
        _updateGUI = new UpdateGUIDelegate(UpdateGUI);
        Task.Factory.StartNew(() => BuildTest());
    }
    private void BuildTest()
    {
        for (int test = 0; test < 5; test++)
            for (int variation = 0; variation < 4; variation++)
                for (int subtest = 0; subtest < 3; subtest++)
                {
                    are.WaitOne();
                    if (this.InvokeRequired)
                        this.Invoke(_updateGUI, test, variation, subtest);
                    else
                        UpdateGUI(test, variation, subtest);
                }
    }
    delegate void UpdateGUIDelegate(int test, int variation, int subtest);
    private UpdateGUIDelegate _updateGUI;
    private void UpdateGUI(int test, int variation, int subtest)
    { }
    private void btn_Click(object sender, EventArgs e)
    {
        are.Set();   
    }
}