如何继续浏览具有多个循环并等待用户反馈的 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();
}
}
提前感谢!
对于这种情况,线程是矫枉过正的。你只需要做一些代码清理和重构,它会立即看起来更好和合乎逻辑。
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();
}
}