文本框不刷新并在一段时间后处于中断模式
Textbox doesn't refresh and is in break mode after a little time
我正在制作一个简单的 wpf 应用程序。它有一个按钮和一个文本框,当您单击该按钮时,它应该会一直更新文本框(请参阅代码)。我有 3 个问题:
- 它不会更新循环中的文本框。
- 当我点击按钮时,它被卡住了,我无法关闭应用程序(只能使用 taskmanager 并停止调试)。
- 如果我让文本框卡住而不关闭它。大约一分钟后,我收到此错误:中断模式屏幕出现 ContextSwitchDeadlock。
我曾尝试通过互联网搜索解决问题,但没有成功。我希望你们能够解决它:)。代码在这里:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Play_Click(object sender, RoutedEventArgs e)
{
int x = RandomNumber();
}
private string TextboxData;
private int RandomNumber()
{
int x = 0;
int i = 0;
Random rng = new Random();
do
{
x = rng.Next(1, 1000000);
i++;
TextboxData += "\r\nAl zo vaak :O" + i; //the rng loop
textBox.Text = TextboxData;
}
while (x != 1);
TextboxData += "\r\nHij heeft zo vaak geprobeerd 1 te halen " + i;
textBox.Text = TextboxData + Environment.NewLine;
return x;
}
}
问题是您的所有操作都是在主 GUI 线程中进行的。
这意味着您的程序无法重绘界面,因为它正忙于循环执行代码。
为了获得预期的结果,您需要异步执行循环。但是我们必须记住,GUI 应该只从 GUI 线程更新(这是框架要求)。
由于快速计算,文本框更新过于频繁。您可以考虑使用 Thread.Sleep(100)
.
解决方法如下:
private async void Play_Click(object sender, RoutedEventArgs e)
{
int x = await RandomNumber();
}
private async Task<int> RandomNumber()
{
int x = 0;
int i = 0;
string text = string.Empty;
Random rng = new Random();
// This will start work in background. Leaving GUI thread to it's own tasks.
await Task.Factory.StartNew(() =>
{
do
{
x = rng.Next(1, 1000000);
i++;
text = "\r\nAl zo vaak :O" + i.ToString(); //the rng loop
// This will invoke textbox update in GUI thread satisfying update requirement.
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(() => { textBox.AppendText(text); }));
// We will make it slower in order to see updates at adequate rate.
Thread.Sleep(100);
}
while (x != 1);
});
// thanks to await we will have this code executed after we found our x==1.
text = "\r\nHij heeft zo vaak geprobeerd 1 te halen " + i;
textBox.AppendText(text);
return x;
}
不要忘记添加以下用法:
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
编辑:我不知道你为什么要从 RandomNumber() 中获得 return 值(它永远是 1。所以它是无意义的)。但是为了正确处理这个问题,我们需要将 async
添加到我们的签名中以便使用 await
以便我们可以获得一个值,在等待块和 return 结果之后执行代码。
这是一个比较复杂的话题,我在这里只提一下,以便有正确的解决方案。如果您感兴趣 - google '.net async await'。但我建议留着以后用:)
此外,我删除了 TextBoxData
字段并将其替换为局部变量,并按照@KevinKal 的建议使用了 textbox.AppendText()
。
我正在制作一个简单的 wpf 应用程序。它有一个按钮和一个文本框,当您单击该按钮时,它应该会一直更新文本框(请参阅代码)。我有 3 个问题:
- 它不会更新循环中的文本框。
- 当我点击按钮时,它被卡住了,我无法关闭应用程序(只能使用 taskmanager 并停止调试)。
- 如果我让文本框卡住而不关闭它。大约一分钟后,我收到此错误:中断模式屏幕出现 ContextSwitchDeadlock。
我曾尝试通过互联网搜索解决问题,但没有成功。我希望你们能够解决它:)。代码在这里:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Play_Click(object sender, RoutedEventArgs e)
{
int x = RandomNumber();
}
private string TextboxData;
private int RandomNumber()
{
int x = 0;
int i = 0;
Random rng = new Random();
do
{
x = rng.Next(1, 1000000);
i++;
TextboxData += "\r\nAl zo vaak :O" + i; //the rng loop
textBox.Text = TextboxData;
}
while (x != 1);
TextboxData += "\r\nHij heeft zo vaak geprobeerd 1 te halen " + i;
textBox.Text = TextboxData + Environment.NewLine;
return x;
}
}
问题是您的所有操作都是在主 GUI 线程中进行的。 这意味着您的程序无法重绘界面,因为它正忙于循环执行代码。
为了获得预期的结果,您需要异步执行循环。但是我们必须记住,GUI 应该只从 GUI 线程更新(这是框架要求)。
由于快速计算,文本框更新过于频繁。您可以考虑使用 Thread.Sleep(100)
.
解决方法如下:
private async void Play_Click(object sender, RoutedEventArgs e)
{
int x = await RandomNumber();
}
private async Task<int> RandomNumber()
{
int x = 0;
int i = 0;
string text = string.Empty;
Random rng = new Random();
// This will start work in background. Leaving GUI thread to it's own tasks.
await Task.Factory.StartNew(() =>
{
do
{
x = rng.Next(1, 1000000);
i++;
text = "\r\nAl zo vaak :O" + i.ToString(); //the rng loop
// This will invoke textbox update in GUI thread satisfying update requirement.
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(() => { textBox.AppendText(text); }));
// We will make it slower in order to see updates at adequate rate.
Thread.Sleep(100);
}
while (x != 1);
});
// thanks to await we will have this code executed after we found our x==1.
text = "\r\nHij heeft zo vaak geprobeerd 1 te halen " + i;
textBox.AppendText(text);
return x;
}
不要忘记添加以下用法:
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
编辑:我不知道你为什么要从 RandomNumber() 中获得 return 值(它永远是 1。所以它是无意义的)。但是为了正确处理这个问题,我们需要将 async
添加到我们的签名中以便使用 await
以便我们可以获得一个值,在等待块和 return 结果之后执行代码。
这是一个比较复杂的话题,我在这里只提一下,以便有正确的解决方案。如果您感兴趣 - google '.net async await'。但我建议留着以后用:)
此外,我删除了 TextBoxData
字段并将其替换为局部变量,并按照@KevinKal 的建议使用了 textbox.AppendText()
。