WPF中,UI界面不能实时更新的问题,跪求solution!!!!!!!

longhuadaxia 2011-01-05 08:26:28
WPF程序代码如下,界面不能实时更新,如果循环次数少还好,循环次数多的话,就很明显了,下面是我写的一个例子,这个例子中虽然textbox的值早就变了,但是界面上一点变化都没有,请教各位大侠,怎么样让他自动更新呢?
如果采用多线程,该怎么改丫? 谢谢各位了,各抒己见,畅所欲言啊。凑个吉利点的分数


public partial class Window1 : Window
{
DispatcherTimer tm = new DispatcherTimer();

public Window1()
{
InitializeComponent();
tm.Tick += new EventHandler(tm_Tick);
tm.Interval = TimeSpan.FromSeconds(0.05);

}

private void button1_Click(object sender, RoutedEventArgs e)
{
tm.Start();
progbar.Value = 0;
progbar.Maximum = 100;
tm_Tick(sender, e);
for (int i = 0; i < 1000000; i++)
{
string passedSns = i + Environment.NewLine + this.textBox1.Text;
this.textBox1.Text = passedSns;
textBox1.Foreground = new SolidColorBrush(Colors.Red);
}
}

private void tm_Tick(object sender, EventArgs e)
{
progbar.Value++;

if (progbar.Value == progbar.Maximum)
{
tm.Stop();
}
}

}
...全文
1757 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
lethwei 2011-01-06
  • 打赏
  • 举报
回复
跟 tm_Tick() 无关, lz 需要搞清楚, 一般来说一个 WPF 窗口程序, 只有一个 UI 线程, 如果这个线程停在某个函数, UI 将会被阻塞, 所有其他的界面操作都无法进行
以 lz 的代码为例

private void button1_Click(object sender, RoutedEventArgs e)
{
tm.Start();
progbar.Value = 0;
progbar.Maximum = 100;
tm_Tick(sender, e);
for (int i = 0; i < 1000000; i++)
{
string passedSns = i + Environment.NewLine + this.textBox1.Text;
this.textBox1.Text = passedSns;
textBox1.Foreground = new SolidColorBrush(Colors.Red);
}
}

如果循环很大的话, button1_Click 将运行相当长一段时间, 而这段时间内, 其他 UI 功能都需要等待 button1_Click 的结束, 即 tm_Tick() 也在等待中
所以解决办法是 button1_Click 中耗时长的功能放到另一个线程去跑, 不要阻塞 UI
longhuadaxia 2011-01-06
  • 打赏
  • 举报
回复
3楼的资料很给力,6楼的多线程浪费资源太多,每次创建一个Thread,OS都会创建Thread对象,而使用完后该Thread就会被销毁。创建销毁线程对象都是耗时的工作。

修改后,代码如下,可以同步更新了:
private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);


public Window1()
{
InitializeComponent();
//tm.Tick += new EventHandler(tm_Tick);
//tm.Interval = TimeSpan.FromSeconds(0.05);

}

private void button1_Click(object sender, RoutedEventArgs e)
{
//tm.Start();
progbar.Value = 0;
progbar.Maximum = 1000;
//tm_Tick(sender, e);

double value = 0;

UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(progbar.SetValue);

for (int i = 0; i < 1000; i++)
{
if (value <= progbar.Maximum)
{
value += 1;

Dispatcher.Invoke(updatePbDelegate, System.Windows.Threading.DispatcherPriority.Background,
new object[] { ProgressBar.ValueProperty, value });
}

string passedSns = i + Environment.NewLine + this.textBox1.Text;
this.textBox1.Text = passedSns;
textBox1.Foreground = new SolidColorBrush(Colors.Red);
}
}
windhuan 2011-01-05
  • 打赏
  • 举报
回复

private void button1_Click(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(new ThreadStart(Run));
thread.IsBackground = true;
thread.Start();
}


public void Run()
{
for (int i = 0; i < 1000; i++)
{
this.Dispatcher.BeginInvoke((Action)delegate()
{
string passedSns = i + Environment.NewLine + this.textBox1.Text;
this.textBox1.Text = passedSns;
textBox1.Foreground = new SolidColorBrush(Colors.Red);
});

//给界面更新TextBox的时间
Thread.Sleep(10);
}
}
绿色夹克衫 2011-01-05
  • 打赏
  • 举报
回复
LZ这样不会把界面线程弄死么?
longhuadaxia 2011-01-05
  • 打赏
  • 举报
回复
时间事件里面的是一个processbar控件,也是和textbox一样,要等到循环结束,才开始显示进度,其实事情早就做完了。

[Quote=引用 2 楼 center182 的回复:]
是不是时间事件里面写的有问题呢?
[/Quote]
wuyq11 2011-01-05
  • 打赏
  • 举报
回复
使用 DispatcherTimer 类来实现类似 Timer 的定时执行事件,该事件使用委托方式实现
http://www.codeproject.com/KB/WPF/WpfProgressBar.aspx
center182 2011-01-05
  • 打赏
  • 举报
回复
是不是时间事件里面写的有问题呢?

110,499

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧