我刚开始编程,经过长时间的休息后遇到了一个小问题。
我正在使用VS2013桌面,并将其创建为GUI程序。
我的问题是,当用于调用逻辑方法的方法运行一次时,我创建了一个工作随机数生成器。生成的数字,文本更新,一切都很好。当它进入循环时,它不会更新我正在修改的对象的text属性,直到它完成整个循环或被破坏。当循环执行时我运行它时,程序基本上会挂起,我必须强制它关闭。
目前我想将发电机设置为在后台无限运行,直到我按下另一个按钮停止它。
我是编程新手,这可能有各种各样的问题,所以如果有任何问题,我会很感激任何有关结构和其他实践的反馈。
以下是代码:
Form1.cs的
// Global
bool boolLooper;
// Setting up the random number generator
private string RandomNumber()
{
RandomNumber rndNumber = new RandomNumber();
string strRandNumber = Convert.ToString(rndNumber.RandomInt(1000, 9999999));
return strRandNumber;
}
// TEST - used in buttonclick event
private void TextUpdates()
{
while (BoolLooper == true)
{
txtID1.Text = RandomNumber();
//txtName1.Text = RandomNumber();
//txtSize1.Text = RandomNumber();
//txtKey1.Text = RandomNumber();
//txtType1.Text = RandomNumber();
}
}
//-----------------------------
// Form - Button Clicks
//-----------------------------
// Button - Activate
private void btnActivate_Click(object sender, EventArgs e)
{
BoolLooper = true;
TextUpdates();
//// Update text once
//txtID1.Text = RandomNumber();
//txtName1.Text = RandomNumber();
//txtSize1.Text = RandomNumber();
//txtKey1.Text = RandomNumber();
//txtType1.Text = RandomNumber();
}
// Button - Stop/Deactivate
private void btnDeactivate_Click(object sender, EventArgs e)
{
BoolLooper = false;
}
//-----------------------------
// Properties
//-----------------------------
public bool BoolLooper
{
get { return boolLooper; }
set { boolLooper = value; }
}
RandomNumber.cs
private static readonly Random intRandom = new Random();
private static readonly object syncLock = new object();
public int RandomInt(int minNum, int maxNum)
{
lock (syncLock)
{
// synchronize
return intRandom.Next(minNum, maxNum);
}
}
对于RandomNumber课程,我在这个网站上找到了一篇很棒的帖子,我将在这篇文章中给予作者:https://stackoverflow.com/a/768001
答案 0 :(得分:2)
您在与UI相同的线程上运行此代码。由于它是单线程的,因此用户界面无法响应,因为它正在忙着运行你的循环。您将要将其卸载到单独的线程或以某种方式作为单独的异步操作。然后,该线程/操作只需要在获取更新时告知UI。
一个简单的例子就是使用a BackgroundWorker
object。
请注意该页面上的示例BackgroundWorker
公开可用于更新UI元素的事件:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
}
还有其他可能的方法。您可以手动创建Thread
并尝试手动同步它,但这也带来了其他潜在问题。而且这里确实没有必要让这个复杂。
您是否需要TextBox
不断更新?或者只是偶尔更新一次?如果更新之间有一些明显的时间段(一秒钟?),那么您可以使用a Timer
来安排定期进行的代码。该结构类似于BackgroundWorker
,因为它会暴露一个事件,用于更新UI。
答案 1 :(得分:1)
您的所有代码都在UI线程上执行。因此,您已停留在while
循环中,并且表单不响应按钮单击(将您的while循环标志设置为false)。这就是我们所说的blocking call
。它会阻止用户界面继续。
通常在这种情况下,您需要查看线程。但是,根据您的代码。我会查看一个计时器,并让它每隔一秒左右打勾。它们非常容易实现,您可以消除while
循环的复杂性,只需执行随机数生成并将其分配给UI控件。 (这也使得你不必将后台线程编组回你的UI线程。)
有关计时器的更多信息: System.Windows.Forms.Timer
答案 2 :(得分:0)
您基本上需要运行每个调用以异步生成新数字。使用.NET Framework,有几种方法可以实现,但我更喜欢使用Task
class。你可以这样做:
public Task RunAsynchronously(Action method)
{
return Task.Factory.StartNew(method);
}
...
RunAsynchronously(() => MethodThatGeneratesRandomNumber());
每次调用此方法时,方法执行都将异步运行。
答案 3 :(得分:0)
您每次都在创建RandomNumber
课程的新实例。只要让它成为你班上的一员。喜欢:
// Global
bool boolLooper;
//Random number generator
RandomNumber rndNumber = new RandomNumber();
并且不需要在方法RandomNumber中创建新实例,只需将其更改为:
private string RandomNumber()
{
string strRandNumber = Convert.ToString(rndNumber.RandomInt(1000, 9999999));
return strRandNumber;
}
更新:我在评论后读了一下Application.DoEvents(),所以使用Invokes,等待任务调用,其他人,但不是这个。
答案 4 :(得分:0)
如果您使用的是.NET 4.5,请更新TextUpdates方法以使用async / await调用,如下例所示
private async void TextUpdates()
{
await Task.Run(() =>
{
while (BoolLooper)
{
txtID1.Invoke((MethodInvoker)(() => txtID1.Text = RandomNumber()));
//txtName1.Text = RandomNumber();
//txtSize1.Text = RandomNumber();
//txtKey1.Text = RandomNumber();
//txtType1.Text = RandomNumber();
}
});
}